为什么使用initCause
调用ExceptionInInitializerError
会导致IllegalStateException
?
public class Test {
public static final void main(String[] ignored) {
try {
ExceptionInInitializerError err = new ExceptionInInitializerError("1. Fail!");
err.initCause(new NullPointerException("null!"));
throw err;
} catch(Exception x) {
x.printStackTrace();
}
System.out.println();
try {
IllegalStateException isx = new IllegalStateException("2. Fail!");
isx.initCause(new NullPointerException("null!"));
throw isx;
} catch(Exception x) {
x.printStackTrace();
}
System.out.println();
try {
throw new IllegalStateException("3. Fail!", new NullPointerException("null!"));
} catch(Exception x) {
x.printStackTrace();
}
}
}
输出:
java.lang.IllegalStateException: Can't overwrite cause with java.lang.NullPointerException: null!
at java.lang.Throwable.initCause(Throwable.java:456)
at Test.main(Test.java:5)
Caused by: java.lang.ExceptionInInitializerError: 1. Fail!
at Test.main(Test.java:4)
java.lang.IllegalStateException: 2. Fail!
at Test.main(Test.java:14)
Caused by: java.lang.NullPointerException: null!
at Test.main(Test.java:15)
java.lang.IllegalStateException: 3. Fail!
at Test.main(Test.java:24)
Caused by: java.lang.NullPointerException: null!
... 1 more
我在文档中没有看到任何内容,无论是构造函数还是类本身,都说(a)不允许,或者(b)为什么不允许它。我确实在JavaDoc中看到"There is no saved throwable object."
,但对我来说,这意味着可以设置一个 。
这是"只是因为",还是有理由说明为什么你无法设定ExceptionInInitializerError
的原因?
答案 0 :(得分:2)
在我研究这个问题时,我正在查看ExceptionInInitializerError
的源代码。
首先,class JavaDoc中有这个:
从版本1.4开始,此异常已经过改进,以符合通用异常链机制。可以在构造时提供并通过getException()方法访问的“已保存的throwable对象”现在称为原因,并且可以通过Throwable.getCause()方法以及前面提到的“遗留方法”来访问。 “
没有“不要使用initCause
”,但这似乎是你最接近的。
constructors明确地说这是不可能的,内部注释比JavaDoc中的任何内容都要清晰得多(只有“没有保存的throwable对象”):
/**
<P>... There is no saved throwable object.</P>
**/
public ExceptionInInitializerError() {
initCause(null); // Disallow subsequent initCause
}
public ExceptionInInitializerError(Throwable thrown) {
initCause(null); // Disallow subsequent initCause
this.exception = thrown;
}
public ExceptionInInitializerError(String s) {
super(s);
initCause(null); // Disallow subsequent initCause
}
不太明白为什么会这样,但它似乎是遗留代码无法改装的混合物,而且“只是因为”。