Перейти к основному содержимому

Java — попробуйте с ресурсами

· 4 мин. чтения

1. Обзор

Поддержка try-with-resources, представленная в Java 7, позволяет нам объявлять ресурсы, которые будут использоваться в блоке try , с гарантией того, что ресурсы будут закрыты после выполнения этого блока.

Объявленные ресурсы должны реализовать интерфейс AutoCloseable .

2. Использование попытки с ресурсами

Проще говоря, для автоматического закрытия ресурс должен быть объявлен и инициализирован внутри try :

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
writer.println("Hello World");
}

3. Замена trycatch-finally на try- with -resources

Простой и очевидный способ использования новой функциональности try-with-resources — заменить традиционный и многословный блок try-catch-finally .

Давайте сравним следующие примеры кода.

Первый типичный блок try-catch-finally :

Scanner scanner = null;
try {
scanner = new Scanner(new File("test.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}

А вот новое супер лаконичное решение с использованием try-with-resources :

try (Scanner scanner = new Scanner(new File("test.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}

Здесь можно продолжить изучение класса Scanner .

4. попробуйте с ресурсами с несколькими ресурсами

Мы можем просто объявить несколько ресурсов в блоке try-with-resources , разделив их точкой с запятой:

try (Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
while (scanner.hasNext()) {
writer.print(scanner.nextLine());
}
}

5. Пользовательский ресурс с AutoCloseable

Чтобы создать пользовательский ресурс, который будет корректно обрабатываться блоком try-with-resources , класс должен реализовать интерфейсы Closeable или AutoCloseable и переопределить метод close :

public class MyResource implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("Closed MyResource");
}
}

6. Порядок закрытия ресурса

Ресурсы, которые были определены/получены первыми, будут закрыты последними. Давайте рассмотрим пример такого поведения:

Ресурс 1:

public class AutoCloseableResourcesFirst implements AutoCloseable {

public AutoCloseableResourcesFirst() {
System.out.println("Constructor -> AutoCloseableResources_First");
}

public void doSomething() {
System.out.println("Something -> AutoCloseableResources_First");
}

@Override
public void close() throws Exception {
System.out.println("Closed AutoCloseableResources_First");
}
}

Ресурс 2:

public class AutoCloseableResourcesSecond implements AutoCloseable {

public AutoCloseableResourcesSecond() {
System.out.println("Constructor -> AutoCloseableResources_Second");
}

public void doSomething() {
System.out.println("Something -> AutoCloseableResources_Second");
}

@Override
public void close() throws Exception {
System.out.println("Closed AutoCloseableResources_Second");
}
}

Код:

private void orderOfClosingResources() throws Exception {
try (AutoCloseableResourcesFirst af = new AutoCloseableResourcesFirst();
AutoCloseableResourcesSecond as = new AutoCloseableResourcesSecond()) {

af.doSomething();
as.doSomething();
}
}

Выход:

Конструктор -> AutoCloseableResources_First

Конструктор -> AutoCloseableResources_Second

Something -> AutoCloseableResources_First

Something -> AutoCloseableResources_Second

Closed AutoCloseableResources_Second

Closed AutoCloseableResources_First

7. поймать и наконец

Блок try-with-resources может по-прежнему иметь блоки catch `` и finally , которые будут работать так же, как и в традиционном блоке try .

8. Java 9 — эффективные окончательные `` переменные

До Java 9 мы могли использовать свежие переменные только внутри блока try-with-resources :

try (Scanner scanner = new Scanner(new File("testRead.txt")); 
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
// omitted
}

Как показано выше, это было особенно многословно при объявлении нескольких ресурсов. Начиная с Java 9 и как часть JEP 213 , теперь мы можем использовать переменные final или даже эффективно final внутри блока try-with-resources :

final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) {
// omitted
}

Проще говоря, переменная фактически является final , если она не изменяется после первого присваивания, даже если она явно не помечена как final .

Как показано выше, переменная сканера явно объявлена как final , поэтому мы можем использовать ее с блоком try-with-resources . Хотя переменная записи не является явно окончательной, она не меняется после первого присваивания. Таким образом, мы также можем использовать переменную записи .

9. Заключение

В этой статье мы обсудили, как использовать try-with-resources и как заменить try , catch и, наконец , try-with-resources.

Мы также рассмотрели создание пользовательских ресурсов с помощью AutoCloseable и порядок, в котором ресурсы закрываются.

Полный исходный код примера доступен в этом проекте GitHub .