Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как автоматически закрывать ресурсы

Короткий ответ

Объявите ресурс в скобках после try. Java вызовет у него close() при выходе из блока — даже если случилось исключение:

void main() throws IOException {
    Files.writeString(Path.of("data.txt"), "line 1\nline 2\n");
 
    try (BufferedReader reader = Files.newBufferedReader(Path.of("data.txt"))) {
        IO.println(reader.readLine());
    }
}

Результат:

line 1

Несколько ресурсов

Перечислите ресурсы через точку с запятой. Закрываются они в обратном порядке:

void main() throws IOException {
    Files.writeString(Path.of("in.txt"), "hello\n");
 
    try (var reader = Files.newBufferedReader(Path.of("in.txt"));
         var writer = Files.newBufferedWriter(Path.of("out.txt"))) {
        writer.write(reader.readLine().toUpperCase());
    }
    IO.println(Files.readString(Path.of("out.txt")));
}

Результат:

HELLO

Свой ресурс

Любой класс, реализующий AutoCloseable, можно использовать в try:

class Connection implements AutoCloseable {
    Connection() {
        IO.println("open");
    }
 
    @Override
    public void close() {
        IO.println("close");
    }
}
 
void main() {
    try (var connection = new Connection()) {
        IO.println("work");
        throw new IllegalStateException("failed");
    } catch (IllegalStateException e) {
        IO.println("caught: " + e.getMessage());
    }
}

Результат:

open
work
close
caught: failed

Обратите внимание на порядок: ресурс закрывается до того, как выполняется catch.

Частая ошибка

Закрывать ресурс вручную в конце try. Если раньше произойдёт исключение, close() не вызовется:

class Connection implements AutoCloseable {
    @Override
    public void close() {
        IO.println("close");
    }
}
 
void main() {
    try {
        var connection = new Connection();
        Integer.parseInt("x");
        connection.close();
    } catch (NumberFormatException e) {
        IO.println("error, connection left open");
    }
}

Результат:

error, connection left open

Функции из этого ответа

  • try / catch / finally — Перехватывает исключения; finally выполняется всегда, а try с ресурсами сам их закрывает.
  • AutoCloseable — Интерфейс ресурса, который можно закрыть в try-with-resources.
  • BufferedReader — Читает текст построчно с буферизацией — классический способ обработки больших файлов.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.