


try-with-resources закрывает успешно созданные ресурсы при выходе из блока, в том числе после исключения. Ресурс должен реализовывать AutoCloseable. Если ресурсов несколько, они закрываются в обратном порядке объявления.
На Mentoring.digital разберём два вопроса: как безопасно прочитать первую строку файла и как не потерять причину сбоя, если ошибка произошла ещё и при закрытии.
Метод открывает текстовый файл, читает одну строку и освобождает reader. Для пустого файла результатом будет null. Код использует API Java 8 и более новых версий.
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
static String firstLine(Path path) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(
path, StandardCharsets.UTF_8)) {
return reader.readLine();
}
}
Перед фактическим возвратом значения Java вызывает close. Если закрытие завершится исключением, нормального возврата не будет. Объявление throws оставляет вызывающему коду решение, что делать с ошибкой чтения или закрытия.
Представьте учебные ресурсы first и second. Их close печатает имя. В самостоятельном файле Demo.java можно проверить порядок:
public class Demo {
static class Resource implements AutoCloseable {
private final String name;
Resource(String name) { this.name = name; }
public void close() { System.out.println(name); }
}
public static void main(String[] args) {
try (Resource first = new Resource("first");
Resource second = new Resource("second")) {
System.out.println("body");
}
}
}
Ожидаемая последовательность: body, second, first. Если создание second выбросит исключение, уже созданный first всё равно будет закрыт. Объект, создание которого не завершилось, нельзя считать успешно зарегистрированным ресурсом.
Если тело try выбросило исключение, а close выбросил другое, главным остаётся исключение из тела. Ошибку закрытия можно получить через getSuppressed(). Это помогает не заменить исходную причину менее информативным сообщением об освобождении ресурса.
Для эксперимента измените close так, чтобы он выбрасывал исключение, а в теле добавьте throw new IllegalStateException("body failed"). Перехватите Exception снаружи и посмотрите его сообщение и массив подавленных исключений. Делайте это в учебном примере, а не добавляйте искусственные сбои в рабочий сервис.
Закрывайте то, чем владеет текущая операция. Полученный извне поток может принадлежать вызывающему коду: автоматическое закрытие без согласованного контракта оборвёт дальнейшую работу с ним. Возвращать reader из try-with-resources тоже неверно, если вызывающий код ожидает открытый ресурс.
Автоматическое закрытие JDBC-соединения не заменяет явно выбранную политику транзакции. Commit и rollback относятся к отдельному договору обработки данных. Также try-with-resources не обещает, что конкретная реализация close никогда не зависнет или не завершится ошибкой.
Потренировать исключения и ввод-вывод можно на курсах Java с наставником. Проверить управление ресурсами в вашем коде помогут менторы по Java.