try-with-resources
Конструкция try-with-resources, появившаяся в Java 7, гарантирует автоматическое закрытие
любого ресурса, реализующего интерфейс AutoCloseable (или его подинтерфейс Closeable).
Это избавляет программиста от шаблонного кода в finally, где раньше приходилось проверять
null и ловить исключения при закрытии.
Ресурс, объявленный в круглых скобках после try, закрывается автоматически после выхода
из блока — независимо от того, завершился ли блок нормально или с исключением. Если ресурс
бросает исключение при закрытии, оно становится «подавленным» (suppressed) и доступно через
Throwable.getSuppressed().
С Java 9 разрешено использовать в скобках уже существующие effectively final переменные —
не обязательно объявлять ресурс прямо внутри try.
Синтаксис
try (Resource1 r1 = new Resource1();
Resource2 r2 = new Resource2()) {
// работа с r1, r2
} catch (Exception e) {
// обработка
}
// r2 и r1 уже закрыты (в обратном порядке)
Пример 1. Чтение файла
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("sensors.log"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("Ошибка чтения: " + e.getMessage());
}
}
}
Output (если файла нет):
Ошибка чтения: sensors.log (No such file or directory)
Пример 2. Несколько ресурсов
import java.io.*;
public class CopyFile {
public static void main(String[] args) {
try (FileInputStream in = new FileInputStream("source.txt");
FileOutputStream out = new FileOutputStream("dest.txt")) {
byte[] buf = new byte[1024];
int n;
while ((n = in.read(buf)) != -1) {
out.write(buf, 0, n);
}
System.out.println("Файл скопирован");
} catch (IOException e) {
System.out.println("I/O: " + e.getMessage());
}
}
}
Output (если source.txt отсутствует):
I/O: source.txt (No such file or directory)
Пример 3. Свой AutoCloseable
class FakeSensor implements AutoCloseable {
private final String name;
public FakeSensor(String name) {
this.name = name;
System.out.println("Открыли " + name);
}
public int read() {
return 42;
}
@Override
public void close() {
System.out.println("Закрыли " + name);
}
}
public class ResourceDemo {
public static void main(String[] args) {
try (FakeSensor s = new FakeSensor("DHT22")) {
System.out.println("Чтение: " + s.read());
}
}
}
Output:
Открыли DHT22
Чтение: 42
Закрыли DHT22
Пример 4. Порядок закрытия
class Step implements AutoCloseable {
private final String name;
public Step(String name) {
this.name = name;
System.out.println("OPEN " + name);
}
@Override
public void close() {
System.out.println("CLOSE " + name);
}
}
public class OrderDemo {
public static void main(String[] args) {
try (Step a = new Step("A");
Step b = new Step("B");
Step c = new Step("C")) {
System.out.println("work");
}
}
}
Output:
OPEN A
OPEN B
OPEN C
work
CLOSE C
CLOSE B
CLOSE A
Пример 5. Подавленные исключения
class BadResource implements AutoCloseable {
@Override
public void close() {
throw new RuntimeException("Ошибка при close()");
}
}
public class SuppressedDemo {
public static void main(String[] args) {
try (BadResource r = new BadResource()) {
throw new RuntimeException("Ошибка в try");
} catch (RuntimeException e) {
System.out.println("Основная: " + e.getMessage());
for (Throwable s : e.getSuppressed()) {
System.out.println("Подавлена: " + s.getMessage());
}
}
}
}
Output:
Основная: Ошибка в try
Подавлена: Ошибка при close()
Подводные камни
Предупреждение
Ресурсы закрываются в обратном порядке объявления.
Исключение из ``close()`` становится подавленным, если уже было исключение из
try.``AutoCloseable.close()`` может бросать
Exception,Closeable.close()— толькоIOException. Выбирайте подходящий интерфейс.Идиома Java 9+ позволяет использовать готовую переменную, но она должна быть effectively final.
Не забывайте про сам ``catch`` — try-with-resources автоматически закроет ресурс, но не обработает исключение за вас.
См. также
Примечание
Материал подготовлен на основе официальной документации Oracle Java Tutorials — The try-with-resources Statement (Oracle Free Documentation License). Текст переведён и переработан, примеры кода написаны заново.