16

我碰巧意识到,情况就是这样。请参阅下面的示例:

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." );
        }
    }
}

它打印:

尝试
关闭。 终于
抓到了

问题

try-with-resources 旨在避免带有 null 检查的混乱 finally 部分,并避免资源泄漏。为什么在 catch 部分之前关闭资源?其背后的原因/想法/限制是什么?

4

1 回答 1

12

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

try-with-resources具有至少一个子句catch和/或一个finally子句的语句称为扩展 try-with-resources语句。

扩展try-with-resources语句的含义:

try ResourceSpecification
    Block
[Catches]
[Finally]

由以下对try-with-resources嵌套在try-catchor try-finallyortry-catch-finally语句中的基本语句的翻译给出:

try {
    try ResourceSpecification
        Block
}
[Catches]
[Finally]

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

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

于 2014-07-31T11:06:17.330 回答