为什么Java不允许从静态初始化块中抛出检查exception?

为什么Java不允许从静态初始化块中抛出检查exception? 这个devise决定背后的原因是什么?

因为您无法在源代码中处理这些经过检查的exception。 您无法控制初始化过程,并且无法从源中调用静态块,因此您可以使用try-catch来包围它们。

因为你不能处理检查exception指出的任何错误,所以决定不允许抛出检查的exception静态块。

静态块不能抛出检查exception,但仍然可以引发未经检查的/运行时exception。 但是根据上面的原因,你将无法处理这些。

总而言之,这个限制防止了(或者至less使开发者更难)构build可能导致应用程序无法恢复的错误的东西。

您可以通过捕获任何检查的exception并重新将其作为一个未经检查的exception重新抛出来解决此问题。 这个未经检查的exception类可以很好地用作包装: java.lang.ExceptionInInitializerError

示例代码:

 protected static class _YieldCurveConfigHelperSingleton { public static YieldCurveConfigHelper _staticInstance; static { try { _staticInstance = new YieldCurveConfigHelper(); } catch (IOException | SAXException | JAXBException e) { throw new ExceptionInInitializerError(e); } } } 

它必须看起来像这样(这不是有效的Java代码)

 // Not a valid Java Code static throws SomeCheckedException { throw new SomeCheckedException(); } 

但是广告如何抓住它? 检查exception需要捕获。 想象一下,可能会初始化类的一些例子(或者可能不是因为它已经被初始化了),而只是为了引起它所引入的复杂性的注意,我把例子放在另一个静态的初始化器中:

 static { try { ClassA a = new ClassA(); Class<ClassB> clazz = Class.forName(ClassB.class); String something = ClassC.SOME_STATIC_FIELD; } catch (Exception oops) { // anybody knows which type might occur? } } 

而另一个令人讨厌的事情 –

 interface MyInterface { final static ClassA a = new ClassA(); } 

想象一下,ClassA有一个静态初始化器引发一个检查的exception:在这种情况下,MyInterface(它是一个“隐藏”静态初始化器的接口)将不得不抛出exception或处理它 – 在接口的exception处理? 最好保持原样。

看看Java语言规范 :这是说,如果静态初始化器失败 一个编译时错误能够突然完成检查exception。

由于没有你写的代码可以调用静态初始化块,所以抛出检查的exceptions是没有用的。 如果可能的话,当被检查的exception抛出时,jvm会做什么? Runtimeexceptions被传播了起来。

我能够编译抛出一个检查exception也……

 static { try { throw new IOException(); } catch (Exception e) { // Do Something } }