Почему метод 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; ключевые части - это последние два абзаца, особенно последнее предложение предпоследнего абзаца (я подчеркнул это):
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
ключевое слово.