Закроется ли ресурс в try-with-resources, если при закрытии будет выброшено исключение в Java
Что проверяют
Понимаете ли вы механику подавленных исключений. Вопрос точечный, и на нём видно, читали ли вы, что происходит под сахаром конструкции.
Как отвечать
Разберите по случаям.
Ресурсы закрываются всегда, в порядке, обратном объявлению, и происходит это до выполнения блоков catch и finally.
- исключение только в
close(): оно и будет выброшено наружу; - исключение в теле
tryи потом вclose(): наружу уходит исключение из тела, а исключение закрытия становится подавленным. Оно не теряется, его видно в стектрейсе с пометкой Suppressed и можно получить черезgetSuppressed(); - несколько ресурсов: закрываются все, независимо друг от друга. Ошибка закрытия одного не мешает закрытию остальных, все они добавляются как подавленные;
- ресурс не был создан (исключение в самом выражении инициализации): закрывать нечего, ранее созданные ресурсы закроются.
Именно ради этого поведения конструкция и появилась: старый вариант с finally и вложенным close терял исходное исключение, потому что ошибка закрытия перекрывала настоящую причину.
try (var conn = pool.get(); var st = conn.prepareStatement(sql)) {
...
} // st закроется первым, потом connПолезно добавить: с Java 9 в скобках можно указывать уже существующую эффективно финальную переменную, а сам ресурс обязан реализовывать AutoCloseable. И что close() в хорошем коде должен быть идемпотентным и не бросать исключений без крайней нужды.
Где спотыкаются
Думают, что ошибка закрытия отменяет закрытие остальных ресурсов.
Ловят только внешнее исключение и не смотрят подавленные, теряя причину.
Пишут свой close() с тяжёлой логикой, которая может упасть, и получают трудноразбираемые ошибки.