Java中的构造函数可以抛出异常吗?

发布于 2024-11-06 09:53:33 字数 20 浏览 1 评论 0原文

构造函数是否允许抛出异常?

Are constructors allowed to throw exceptions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

浪漫之都 2024-11-13 09:53:33

是的,构造函数可以抛出异常。通常这意味着新对象可以立即进行垃圾回收(当然,尽管它可能在一段时间内不会被回收)。不过,如果“半构造”对象在构造函数中较早地使其自身可见(例如,通过分配静态字段或将其自身添加到集合中),则它可能会保留下来。

在构造函数中抛出异常需要注意的一件事:因为调用者(通常)将无法使用新对象,所以构造函数应该小心避免获取非托管资源(文件句柄等)然后抛出异常而不释放它们。例如,如果构造函数尝试打开一个 FileInputStream 和一个 FileOutputStream,并且第一个成功但第二个失败,则应尝试关闭第一个流。当然,如果它是抛出异常的子类构造函数,这会变得更加困难......这一切都变得有点棘手。这不是一个经常出现的问题,但值得考虑。

Yes, constructors can throw exceptions. Usually this means that the new object is immediately eligible for garbage collection (although it may not be collected for some time, of course). It's possible for the "half-constructed" object to stick around though, if it's made itself visible earlier in the constructor (e.g. by assigning a static field, or adding itself to a collection).

One thing to be careful of about throwing exceptions in the constructor: because the caller (usually) will have no way of using the new object, the constructor ought to be careful to avoid acquiring unmanaged resources (file handles etc) and then throwing an exception without releasing them. For example, if the constructor tries to open a FileInputStream and a FileOutputStream, and the first succeeds but the second fails, you should try to close the first stream. This becomes harder if it's a subclass constructor which throws the exception, of course... it all becomes a bit tricky. It's not a problem very often, but it's worth considering.

墨落画卷 2024-11-13 09:53:33

是的,他们可以抛出异常。如果是这样,它们只会被部分初始化,如果不是最终的,则会受到攻击。

以下内容摘自安全编码指南 2.0

可以通过终结器攻击来访问非最终类的部分初始化实例。攻击者重写子类中受保护的 Finalize 方法,并尝试创建该子类的新实例。此尝试失败(在上面的示例中,ClassLoader 的构造函数中的 SecurityManager 检查会引发安全异常),但攻击者只是忽略任何异常并等待虚拟机对部分初始化的对象执行终结。当发生这种情况时,会调用恶意的 Finalize 方法实现,从而使攻击者能够访问此方法,即对正在最终确定的对象的引用。尽管该对象仅部分初始化,但攻击者仍然可以调用其上的方法(从而绕过 SecurityManager 检查)。

Yes, they can throw exceptions. If so, they will only be partially initialized and if non-final, subject to attack.

The following is from the Secure Coding Guidelines 2.0.

Partially initialized instances of a non-final class can be accessed via a finalizer attack. The attacker overrides the protected finalize method in a subclass, and attempts to create a new instance of that subclass. This attempt fails (in the above example, the SecurityManager check in ClassLoader's constructor throws a security exception), but the attacker simply ignores any exception and waits for the virtual machine to perform finalization on the partially initialized object. When that occurs the malicious finalize method implementation is invoked, giving the attacker access to this, a reference to the object being finalized. Although the object is only partially initialized, the attacker can still invoke methods on it (thereby circumventing the SecurityManager check).

你对谁都笑 2024-11-13 09:53:33

绝对地。

如果构造函数没有收到有效的输入,或者无法以有效的方式构造对象,那么它没有其他选择,只能抛出异常并警告其调用者。

Absolutely.

If the constructor doesn't receive valid input, or can't construct the object in a valid manner, it has no other option but to throw an exception and alert its caller.

遮云壑 2024-11-13 09:53:33

是的,它可以抛出异常,您也可以在构造函数的签名中声明该异常,如下例所示:

public class ConstructorTest
{
    public ConstructorTest() throws InterruptedException
    {
        System.out.println("Preparing object....");
        Thread.sleep(1000);
        System.out.println("Object ready");
    }

    public static void main(String ... args)
    {
        try
        {
            ConstructorTest test = new ConstructorTest();
        }
        catch (InterruptedException e)
        {
            System.out.println("Got interrupted...");
        }
    }
}

Yes, it can throw an exception and you can declare that in the signature of the constructor too as shown in the example below:

public class ConstructorTest
{
    public ConstructorTest() throws InterruptedException
    {
        System.out.println("Preparing object....");
        Thread.sleep(1000);
        System.out.println("Object ready");
    }

    public static void main(String ... args)
    {
        try
        {
            ConstructorTest test = new ConstructorTest();
        }
        catch (InterruptedException e)
        {
            System.out.println("Got interrupted...");
        }
    }
}
合约呢 2024-11-13 09:53:33

是的,构造函数可以抛出异常。

然而,在选择异常时要非常明智——受控异常或非受控异常。未经检查的异常基本上是 RuntimeException 的子类。

在几乎所有情况下(我无法想出这种情况的例外),您需要抛出一个已检查的异常。原因是未经检查的异常(如 NullPointerException)通常是由于编程错误(如未充分验证输入)造成的。

检查异常提供的优点是程序员被迫在其实例化代码中捕获异常,从而意识到创建对象实例可能会失败。当然,只有代码审查才能发现吞下异常的不良编程习惯。

Yes, constructors are allowed to throw exceptions.

However, be very wise in choosing what exceptions they should be - checked exceptions or unchecked. Unchecked exceptions are basically subclasses of RuntimeException.

In almost all cases (I could not come up with an exception to this case), you'll need to throw a checked exception. The reason being that unchecked exceptions (like NullPointerException) are normally due to programming errors (like not validating inputs sufficiently).

The advantage that a checked exception offers is that the programmer is forced to catch the exception in his instantiation code, and thereby realizes that there can be a failure to create the object instance. Of course, only a code review will catch the poor programming practice of swallowing an exception.

↘紸啶 2024-11-13 09:53:33

是的。

构造函数只不过是特殊方法,并且可以像任何其他方法一样抛出异常。

Yes.

Constructors are nothing more than special methods, and can throw exceptions like any other method.

别在捏我脸啦 2024-11-13 09:53:33

是的,构造函数允许抛出异常。

在创建对象之前,有一些场景,例如我们可以将参数发送到构造函数(参数化构造函数),参数验证应该在构造函数中处理并抛出验证异常。

安全检查是在构造函数中引发异常的另一个常见用例。有些对象在创建过程中需要进行安全检查。如果构造函数执行可能不安全或敏感的操作,我们可以抛出异常。

例子:-

public class Employee{
     private String name;
     private Integer age;
     public Employee(String name, Integer age) throws Exception{
         if (StringUtils.isEmpty(name)){
             throw new Exception("Name can not be empty");
         }
         if (age == null || age  100){
              throw new Exception("Entered age is not a valid one");
         }
         this.name = name;
         this.age = age;
    }
}

Yes, constructors to allow to throw an exception.

Before object creation, there are some scenario's like we can send parameters to the constructors(parameterized constructors) the parameters validation should be handled in the constructors and to throw the validation exception.

Security checks are another common use case for throwing exceptions in the constructor. Some of the objects need security checks during their creation. We can throw exceptions if the constructor performs a possibly unsafe or sensitive operation.

Example:-

public class Employee{
     private String name;
     private Integer age;
     public Employee(String name, Integer age) throws Exception{
         if (StringUtils.isEmpty(name)){
             throw new Exception("Name can not be empty");
         }
         if (age == null || age  100){
              throw new Exception("Entered age is not a valid one");
         }
         this.name = name;
         this.age = age;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文