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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1371369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 11:16:17  来源:igfitidea点击:

Can constructors throw exceptions in Java?

javaexceptionconstructor

提问by Mahmoud Hanafy

Are constructors allowed to throw exceptions?

允许构造函数抛出异常吗?

采纳答案by Jon Skeet

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 FileInputStreamand 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.

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

回答by Yuval

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.

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

回答by Isaac

Yes.

是的。

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

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

回答by Vineet Reynolds

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.

但是,在选择它们应该是什么异常时要非常明智 - 检查异常或未检查异常。未经检查的异常基本上是 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).

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

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.

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

回答by Billy Bob Bain

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.

以下内容来自安全编码指南 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).

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

回答by V_Singh

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...");
        }
    }
}