如果构造函数抛出异常,是否在try-with-resources习惯用法上调用close方法?

P45*_*ent 6 java try-with-resources

我有一个基类Base和一个Child扩展它的子类.Base实施java.lang.AutoCloseable.

让我们假设构造函数Child抛出一个Foo.

现在考虑

try (Base c = new Child()){
    /*Some code*/
} catch (final Foo e){
    /*Some more code*/
}
Run Code Online (Sandbox Code Playgroud)

Base#close如果抛出异常,是否调用该方法?它不在我的机器上,但这是JLS标准化的东西吗?

Tun*_*aki 11

是的,close不会被叫.这在JLS 第14.20.3节中规定:

资源按从左到右的顺序初始化.如果资源无法初始化(即,其初始化程序表达式抛出异常),则会关闭try-with-resources语句到目前为止初始化的所有资源.如果所有资源都成功初始化,则try块将正常执行,然后关闭try-with-resources语句的所有非空资源.

资源以与初始化资源相反的顺序关闭.仅当资源初始化为非空值时才关闭资源.关闭一个资源的例外不会阻止关闭其他资源.如果先前由初始化程序,try块或资源关闭抛出异常,则会抑制此类异常.

在这种情况下,构造函数中会抛出异常,因此资源不会初始化为非null值.因此,close不调用该方法.


use*_*ica 6

close不会被叫.调用它是没有意义的,因为你没有一个完全构造的对象可以关闭,在类似的调用中,你甚至可能没有输入构造函数:

try (Base b = makeBase()) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

这里makeBase

Base makeBase() {
    throw new RuntimeException();
}
Run Code Online (Sandbox Code Playgroud)

  • @ P45Imminent:Java没有任何基础子对象的概念.没有完全构造的"基础"对象; 在"Child"构造函数完成之前,该对象尚未完全构造. (5认同)
  • 但是基类*是*完全构造的。这就是我正在与之抗争的。 (2认同)