是否允许构造函数抛出异常?
答案 0 :(得分:347)
是的,构造函数可以抛出异常。通常这意味着新对象立即有资格进行垃圾收集(当然,它可能在一段时间内不会被收集)。如果它在构造函数中早先可见(例如,通过指定静态字段或将其自身添加到集合中),那么“半构造”对象可能会粘在一起。(
在构造函数中抛出异常要注意一件事:因为调用者(通常)无法使用新对象,构造函数应该小心避免获取非托管资源(文件句柄等)然后抛出异常而不释放它们。例如,如果构造函数尝试打开FileInputStream
和FileOutputStream
,并且第一个成功但第二个失败,则应尝试关闭第一个流。如果它是抛出异常的子类构造函数,这会变得更难,当然......这一切都变得有点棘手。这不是经常出现的问题,但值得考虑。
答案 1 :(得分:78)
是的,他们可以抛出异常。如果是这样,它们将仅部分初始化,如果不是最终的,则受到攻击。
以下内容来自Secure Coding Guidelines 2.0。
可以通过终结器攻击访问非最终类的部分初始化实例。攻击者覆盖子类中受保护的finalize方法,并尝试创建该子类的新实例。此尝试失败(在上面的示例中,SecurityManager检查ClassLoader的构造函数会引发安全性异常),但攻击者只是忽略任何异常并等待虚拟机对部分初始化的对象执行最终化。当发生这种情况时,将调用恶意终结方法实现,使攻击者能够访问此对象,即对正在最终确定的对象的引用。尽管该对象仅部分初始化,但攻击者仍然可以在其上调用方法(从而绕过SecurityManager检查)。
答案 2 :(得分:32)
绝对。
如果构造函数没有收到有效的输入,或者无法以有效的方式构造对象,那么除了抛出异常并提醒其调用者之外别无选择。
答案 3 :(得分:14)
是的,它可以抛出一个异常,您也可以在构造函数的签名中声明它,如下例所示:
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...");
}
}
}
答案 4 :(得分:11)
是的,允许构造函数抛出异常。
但是,在选择应该是什么例外时要非常明智 - 检查例外或未选中。未经检查的异常基本上是RuntimeException的子类。
在几乎所有情况下(我都无法对此案例提出异常),您需要抛出一个已检查的异常。原因是未经检查的异常(如NullPointerException)通常是由于编程错误(如未充分验证输入)。
检查异常提供的优点是程序员被迫在其实例化代码中捕获异常,从而意识到可能无法创建对象实例。当然,只有代码审查才能捕捉到吞噬异常的糟糕编程习惯。
答案 5 :(得分:7)
是。
构造函数只不过是特殊方法,并且可以像任何其他方法一样抛出异常。
答案 6 :(得分:-3)
是的,它可以像其他方法一样抛出异常