我有一个基类Base
和一个Child
扩展它的子类.Base
实施java.lang.AutoCloseable
.
让我们假设构造函数Child
抛出一个Foo
.
现在考虑
try (Base c = new Child()){ /*Some code*/ } catch (final Foo e){ /*Some more code*/ }
Base#close
如果抛出异常,是否调用该方法?它不在我的机器上,但这是JLS标准化的东西吗?
是的,close
不会被叫.这在JLS 第14.20.3节中规定:
资源按从左到右的顺序初始化.如果资源无法初始化(即,其初始化程序表达式抛出异常),则会关闭try-with-resources语句到目前为止初始化的所有资源.如果所有资源都成功初始化,则try块将正常执行,然后关闭try-with-resources语句的所有非空资源.
资源以与初始化资源相反的顺序关闭.仅当资源初始化为非空值时才关闭资源.关闭一个资源的例外不会阻止关闭其他资源.如果先前由初始化程序,try块或资源关闭抛出异常,则会抑制此类异常.
在这种情况下,构造函数中会抛出异常,因此资源不会初始化为非null值.因此,close
不调用该方法.
close
不会被叫.调用它是没有意义的,因为你没有一个完全构造的对象可以关闭,在类似的调用中,你甚至可能没有输入构造函数:
try (Base b = makeBase()) { ... }
这里makeBase
是
Base makeBase() { throw new RuntimeException(); }