В този урок ще научим за инструкцията try-with-resources за автоматично затваряне на ресурси.
В try-with-resources
изявлението се затварят автоматично, всички ресурси в края на изявлението. Ресурсът е обект, който трябва да бъде затворен в края на програмата.
Синтаксисът му е:
try (resource declaration) ( // use of the resource ) catch (ExceptionType e1) ( // catch block )
Както се вижда от горния синтаксис, ние декларираме try-with-resources
изявлението от,
- деклариране и инстанциране на ресурса в рамките на
try
клаузата. - указване и обработка на всички изключения, които могат да се появят при затваряне на ресурса
Забележка: Опитът try-with-resources затваря всички ресурси, които реализират интерфейса AutoCloseable.
Нека вземем пример, който реализира try-with-resources
изявлението.
Пример 1: опитайте с ресурси
import java.io.*; class Main ( public static void main(String() args) ( String line; try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) ( while ((line = br.readLine()) != null) ( System.out.println("Line =>"+line); ) ) catch (IOException e) ( System.out.println("IOException in try block =>" + e.getMessage()); ) ) )
Изход, ако файлът test.txt не е намерен.
IOException в try-with-resources block => test.txt (Няма такъв файл или директория)
Изход, ако е намерен файл test.txt.
Въвеждане на блок try-with-resources Line => тестов ред
В този пример използваме екземпляр на BufferedReader за четене на данни от test.txt
файла.
Декларирането и създаването на екземпляр на BufferedReader вътре в try-with-resources
израза гарантира, че неговият екземпляр е затворен, независимо дали try
изразът завършва нормално или изхвърля изключение.
Ако възникне изключение, то може да бъде обработено с помощта на блокове за обработка на изключения или ключовата дума throws.
Потиснати изключения
В горния пример изключенията могат да бъдат изхвърлени от try-with-resources
изявлението, когато:
- Файлът
test.txt
не е намерен. - Затваряне на
BufferedReader
обекта.
Изключение може да бъде хвърлено и от try
блока, тъй като четенето на файл може да се провали по много причини по всяко време.
Ако се хвърлят изключения както от try
блока, така и от try-with-resources
оператора, изключението от try
блока се изхвърля и изключение от try-with-resources
израза се потиска.
Извличане на потиснати изключения
В Java 7 и по-късно потиснатите изключения могат да бъдат извлечени чрез извикване на Throwable.getSuppressed()
метода от изключението, хвърлено от try
блока.
Този метод връща масив от всички потиснати изключения. Получаваме потиснатите изключения в catch
блока.
catch(IOException e) ( System.out.println("Thrown exception=>" + e.getMessage()); Throwable() suppressedExceptions = e.getSuppressed(); for (int i=0; i" + suppressedExceptions(i)); ) )
Предимства на използването на опит с ресурси
Ето предимствата на използването на try-with-resources:
1. накрая не се изисква блок за затваряне на ресурса
Преди Java 7 да представи тази функция, трябваше да използваме finally
блока, за да гарантираме, че ресурсът е затворен, за да се избегнат изтичания на ресурси.
Ето програма, подобна на Пример 1 . Въпреки това, в тази програма, ние използвахме окончателно блок за затваряне на ресурси.
Пример 2: Затворете ресурса с помощта на блок block
import java.io.*; class Main ( public static void main(String() args) ( BufferedReader br = null; String line; try ( System.out.println("Entering try block"); br = new BufferedReader(new FileReader("test.txt")); while ((line = br.readLine()) != null) ( System.out.println("Line =>"+line); ) ) catch (IOException e) ( System.out.println("IOException in try block =>" + e.getMessage()); ) finally ( System.out.println("Entering finally block"); try ( if (br != null) ( br.close(); ) ) catch (IOException e) ( System.out.println("IOException in finally block =>"+e.getMessage()); ) ) ) )
Изход
Въвеждане на блок за опити Line => ред от файл test.txt Въвеждане на окончателно блок
Както можем да видим от горния пример, използването на finally
блок за почистване на ресурси прави кода по-сложен.
Забелязвате ли и try… catch
блока в finally
блока? Това е така, защото IOException
може да възникне и при затваряне на BufferedReader
екземпляра вътре в този finally
блок, така че той също се улавя и обработва.
В try-with-resources
изявлението прави автоматично управление на ресурсите . Не е необходимо изрично да затваряме ресурсите, тъй като JVM автоматично ги затваря. Това прави кода по-четлив и по-лесен за писане.
2. опитайте с ресурси с множество ресурси
Можем да декларираме повече от един ресурс в try-with-resources
изявлението, като ги разделяме с точка и запетая;
Пример 3: опитайте с множество ресурси
import java.io.*; import java.util.*; class Main ( public static void main(String() args) throws IOException( try (Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) ( while (scanner.hasNext()) ( writer.print(scanner.nextLine()); ) ) ) )
Ако тази програма се изпълнява, без да генерира изключения, Scanner
обектът чете ред от testRead.txt
файла и го записва в нов testWrite.txt
файл.
Когато са направени множество декларации, try-with-resources
изразът затваря тези ресурси в обратен ред. В този пример PrintWriter
обектът се затваря първо и след това Scanner
обектът се затваря.
Java 9 подобряване на опит с ресурси
В Java 7 има ограничение за try-with-resources
изявлението. Ресурсът трябва да бъде деклариран локално в рамките на своя блок.
try (Scanner scanner = new Scanner(new File("testRead.txt"))) ( // code )
Ако декларирахме ресурса извън блока в Java 7, той би генерирал съобщение за грешка.
Scanner scanner = new Scanner(new File("testRead.txt")); try (scanner) ( // code )
За да се справи с тази грешка, Java 9 подобри try-with-resources
изявлението, така че препратката към ресурса може да се използва, дори ако не е декларирана локално. Горният код сега ще се изпълни без никаква грешка при компилацията.