try-with-resources

Тема дорожной карты · Java

try-with-resources — это языковая возможность Java 7, автоматизирующая закрытие любого AutoCloseable-ресурса — JDBC Connection, PreparedStatement, ResultSet, NIO Channel, InputStream, OutputStream или любого пользовательского ресурса, — гарантируя вызов close() даже при возникновении исключения и устраняя целый класс ошибок утечки ресурсов. Синтаксис объявляет один или несколько ресурсов в скобках после try: try (Connection conn = ds.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ... } — JVM вызывает close() на каждом ресурсе в обратном порядке объявления при выходе из блока, как в нормальных, так и в исключительных ситуациях. try-with-resources корректно обрабатывает подавленные исключения: если и тело, и close() бросают исключения, исключение из close() прикрепляется как подавленное через Throwable.addSuppressed(), а не игнорируется молча, делая полную цепочку сбоев доступной для отладки. В Java 9+ переменная, уже хранящая AutoCloseable-объект и являющаяся финальной или фактически финальной, может быть указана непосредственно в списке ресурсов (try (existing) { ... }), уменьшая вложенность при создании ресурсов вне оператора. try-with-resources — это идиоматический Java-паттерн для всех операций с I/O и базами данных, заменяющий громоздкие блоки finally в JDBC, NIO, Java Serialization и Spring JDBC-коде, и настоятельно рекомендован инструментами статического анализа SpotBugs и SonarQube в любой JDK-кодовой базе.

Как это работает

try-with-resources делится на checked (нужно объявить или обработать — IOException, SQLException) и unchecked (RuntimeException — NullPointerException, IllegalArgumentException). try { } catch (...) { } finally { } или try-with-resources (try (var x = ...) { }) для AutoCloseable-типов — рекомендуется для файлов/сокетов/соединений. Multi-catch (catch (IOException | SQLException e)) сокращает дублирование. Всегда сохраняйте cause (throw new MyException(msg, cause)).

Когда применять

Checked exceptions — для восстановимых условий в API библиотек (вызывающий решает); unchecked (RuntimeException) — для программных ошибок. Оборачивайте checked exceptions на границах модулей, чтобы stack trace upstream оставался чистым. try-with-resources — для всего AutoCloseable. Логируйте с throwable (log.error("...", e)) — slf4j отформатирует со stack trace.

Типичные ошибки

Ловушки try-with-resources: catch (Exception e) { } тихо съедает каждую ошибку (тихий убийца); checked exceptions для того, что должно быть runtime-ошибкой (многословные declarations повсюду); rewrap exception теряет cause (throw new MyException(msg) без e — stack trace пропал); finally-блок, бросающий exception (оригинальное теряется).

Связанные понятия

Полезные ресурсы