为什么不能用ExceptionInInitializerError调用initCause?

时间:2014-07-06 20:10:17

标签: java exception error-handling

为什么使用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的原因?

1 个答案:

答案 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
}

不太明白为什么会这样,但它似乎是遗留代码无法改装的混合物,而且“只是因为”。