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


绝对的。

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


是的。

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


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

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.


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

但是,在选择异常时要非常明智——检查异常还是未检查异常。未检查的异常基本上是RuntimeException的子类。

在几乎所有的情况下(我找不到这种情况的异常),您都需要抛出一个受控异常。原因是未检查的异常(如NullPointerException)通常是由于编程错误(如没有充分验证输入)。

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


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

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


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

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