Почему метод close () ресурса вызывается перед catch в конструкции try-with-resources в Java?

я случайно понял, что это так. См. этот пример ниже:

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 разработан, чтобы избежать беспорядочных разделов finally с нулевыми проверками и избежать утечки ресурсов. Почему ресурсы закрываются до раздела catch? В чем причина/идея/ограничение?

1 ответов


ответ можно найти в JLS §14.20.3.2; ключевыми частями являются последние два абзаца, особенно последнее предложение предпоследнего абзаца (я подчеркнул Это):

A try-with-resources заявление по крайней мере с одним catch пункт и/или finally статья называется продлен try-with-resources заявление.

значение расширенного try-with-resources о себе:

try ResourceSpecification
    Block
[Catches]
[Finally]

дается следующее перевод на базовый try-with-resources оператор, вложенный в try-catch или try-finally или try-catch-finally о себе:

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

эффект перевод ставить спецификация ресурсов "внутри"try заявление. это позволяет catch предложение расширенного try-with-resources заявление, чтобы поймать исключение при инициализации или закрытия любого ресурса.

кроме того, все ресурсы будут закрыты (или попытаются быть закрыто) к тому времени finally блок выполняется в соответствии с целями finally ключевое слово.