V tomto kurzu se dozvíme o příkazu try-with-resources k automatickému zavření prostředků.
Příkaz try-with-resources
na konci výpisu automaticky zavře všechny prostředky. Prostředek je objekt, který má být uzavřen na konci programu.
Jeho syntaxe je:
try (resource declaration) ( // use of the resource ) catch (ExceptionType e1) ( // catch block )
Jak je vidět z výše uvedené syntaxe, deklarujeme try-with-resources
prohlášení,
- deklarace a vytvoření instance prostředku v
try
klauzuli. - určení a zpracování všech výjimek, které mohou být vyvolány při zavírání prostředku.
Poznámka: Příkaz try-with-resources zavře všechny prostředky, které implementují rozhraní AutoCloseable.
Vezměme si příklad, který try-with-resources
prohlášení implementuje .
Příklad 1: try-with-resources
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()); ) ) )
Výstup, pokud soubor test.txt nebyl nalezen.
IOException in try-with-resources block => test.txt (Žádný takový soubor nebo adresář)
Výstup, pokud bude nalezen soubor test.txt.
Vstup do bloku try-with-resources Line => testovací řádek
V tomto příkladu používáme instanci BufferedReader ke čtení dat ze test.txt
souboru.
Deklarace a vytvoření instance BufferedReader uvnitř try-with-resources
příkazu zajišťuje, že jeho instance je uzavřena bez ohledu na to, zda se try
příkaz dokončí normálně nebo vyvolá výjimku.Declaring and instantiating the BufferedReader inside the statement ensures that its instance is closed depending on whether the statement completes normal or throws an exception.
Pokud dojde k výjimce, lze ji zpracovat pomocí bloků zpracování výjimek nebo klíčového slova throws.
Potlačené výjimky
Ve výše uvedeném příkladu lze z try-with-resources
příkazu vyvolat výjimky, když:
- Soubor
test.txt
nebyl nalezen. - Uzavření
BufferedReader
objektu.
Výjimku lze také vyvolat z try
bloku, protože čtení souboru může kdykoli selhat z mnoha důvodů.
Pokud jsou vyvolány výjimky z try
bloku i z try-with-resources
příkazu, try
je vyvolána výjimka z bloku a výjimka z try-with-resources
příkazu je potlačena.
Načítání potlačených výjimek
V Javě 7 a novějších potlačené výjimky lze načíst voláním Throwable.getSuppressed()
metody z výjimky vyvolané try
blokem.
Tato metoda vrací pole všech potlačených výjimek. Dostaneme potlačené výjimky v catch
bloku.
catch(IOException e) ( System.out.println("Thrown exception=>" + e.getMessage()); Throwable() suppressedExceptions = e.getSuppressed(); for (int i=0; i" + suppressedExceptions(i)); ) )
Výhody použití try-with-resources
Tady jsou výhody používání try-with-resources:
1. konečně blokování není nutné k uzavření zdroje
Než Java 7 představila tuto funkci, museli jsme pomocí finally
bloku zajistit, aby byl prostředek uzavřen, aby nedocházelo k únikům prostředků.
Zde je program podobný příkladu 1 . V tomto programu jsme však použili nakonec block k uzavření prostředků.
Příklad 2: Zavřete zdroj pomocí bloku finally
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()); ) ) ) )
Výstup
Zadání bloku try Řádek => řádek ze souboru test.txt Zadání bloku konečně
Jak vidíme z výše uvedeného příkladu, díky použití finally
bloku k vyčištění prostředků je kód složitější.
Všimněte si také try… catch
bloku v finally
bloku? Důvodem je, že IOException
může dojít také při zavírání BufferedReader
instance uvnitř tohoto finally
bloku, takže je také zachycen a zpracován.
Příkaz try-with-resources
provádí automatickou správu prostředků . Prostředky nemusíme explicitně zavírat, protože JVM je automaticky zavírá. Díky tomu je kód čitelnější a snazší na psaní.
2. vyzkoušet zdroje s více prostředky
V try-with-resources
příkazu můžeme deklarovat více než jeden prostředek tak, že je oddělíme středníkem;
Příklad 3: Vyzkoušejte více zdrojů
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()); ) ) ) )
Pokud se tento program spustí bez generování výjimek, Scanner
objekt načte řádek ze testRead.txt
souboru a zapíše jej do nového testWrite.txt
souboru.
Když je provedeno více deklarací, try-with-resources
příkaz zavře tyto prostředky v opačném pořadí. V tomto příkladu je PrintWriter
objekt nejprve uzavřen a poté je Scanner
objekt uzavřen.
Vylepšení vyzkoušení prostředků v prostředí Java 9
V prostředí Java 7 existuje omezení try-with-resources
příkazu. Zdroj musí být deklarován lokálně v rámci svého bloku.
try (Scanner scanner = new Scanner(new File("testRead.txt"))) ( // code )
Pokud bychom prostředek deklarovali mimo blok v Javě 7, vygeneroval by chybovou zprávu.
Scanner scanner = new Scanner(new File("testRead.txt")); try (scanner) ( // code )
Pro řešení této chyby Java 9 vylepšila try-with-resources
příkaz tak, aby bylo možné použít odkaz na prostředek, i když není deklarován lokálně. Výše uvedený kód se nyní spustí bez jakékoli chyby kompilace.