Как работает конструкция try-with-resources в Java?

«Как работает конструкция try-with-resources в Java?» — вопрос из категории Java Core, который задают на 28% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Try-with-resources — это конструкция, введенная в Java 7 для автоматического управления ресурсами, которые необходимо закрывать после использования (например, потоки ввода-вывода, соединения с БД).

Принцип работы: Ресурс, объявленный в круглых скобках после try, должен реализовывать интерфейс java.lang.AutoCloseable. После завершения блока try (нормального или из-за исключения) JVM автоматически вызывает метод close() каждого ресурса.

Преимущества перед try-catch-finally:

  • Код становится короче и чище.
  • Исключения не "маскируются". Если в блоке try и в close() возникли исключения, исключение из try передается вызывающему коду, а исключение из close() добавляется к нему как suppressed (доступно через Throwable.getSuppressed()).

Синтаксис и пример:

import java.io.*;

public class TryWithResourcesDemo {
    public static void main(String[] args) {
        // Ресурсы объявляются в скобках. Они будут закрыты в обратном порядке.
        try (FileInputStream fis = new FileInputStream("input.txt");
             BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {

            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            // Здесь автоматически вызывается reader.close(), затем fis.close()
        } catch (IOException e) { // Ловим возможные исключения
            System.err.println("Ошибка при работе с файлом: " + e.getMessage());
        }
        // Ресурсы уже закрыты, даже если было исключение.
    }
}

Важно: Начиная с Java 9, ресурсы можно объявлять вне блока try, если они являются effectively final.

BufferedReader reader = new BufferedReader(...);
try (reader) { // Допустимо в Java 9+
    // использование reader
}