为什么在Java中的try-with-resources构造中catch之前调用资源的close()方法?

Gáb*_*ták 9 java try-with-resources autocloseable

我碰巧意识到,情况确实如此.请参阅以下示例:

public class AutoClosableTest {
    public static void main(String[] args) throws Exception {
        try (MyClosable instance = new MyClosable()) {
            if (true) {
                System.out.println( "try" );
                throw new Exception("Foo");
            }
        } catch( Exception e ) {
            System.out.println( "Catched" );
        } finally {
            System.out.println( "Finally" );
        }
    }

    public static class MyClosable implements AutoCloseable {
        @Override
        public void close() throws Exception {
            System.out.println( "Closed." );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它打印:

尝试
关闭.
抓住了
最后

try-with-resources旨在避免使用null检查的杂乱的finally段,并避免泄漏的资源.为什么资源在捕获部分之前关闭?它背后的原因/想法/限制是什么?

T.J*_*der 9

答案可以在JLS§14.20.3.2中找到; 关键部分是最后两段,特别是倒数第二段的最后一句(我强调过):

try-with-resources与至少一个语句catch子句和/或一个finally条款被称为扩展的 try-with-resources语句.

扩展try-with-resources声明的含义:

try ResourceSpecification
    Block
[Catches]
[Finally]
Run Code Online (Sandbox Code Playgroud)

通过以下翻译给出try-with-resources嵌套在try-catchor try-finally或or try-catch-finally语句中的基本语句:

try {
    try ResourceSpecification
        Block
}
[Catches]
[Finally]
Run Code Online (Sandbox Code Playgroud)

翻译的效果是将资源规范放在try语句的"内部" .这允许catch扩展try-with-resources语句的子句由于自动初始化或关闭任何资源而捕获异常.

此外,finally在执行块时,所有资源都将被关闭(或尝试关闭),与finally关键字的意图保持一致.