Java - Versuchen Sie es mit Ressourcen

1. Übersicht

Die in Java 7 eingeführte Unterstützung für Try-with-Resources ermöglicht es uns, Ressourcen für die Verwendung in einem Try- Block zu deklarieren, mit der Gewissheit, dass die Ressourcen nach der Ausführung dieses Blocks geschlossen werden.

Die deklarierten Ressourcen müssen die AutoCloseable- Schnittstelle implementieren .

2. Verwenden von Try-with-Resources

Einfach ausgedrückt, um automatisch geschlossen zu werden, muss eine Ressource innerhalb des Versuchs deklariert und initialisiert werden , wie unten gezeigt:

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

3. Ersetzen von try - catch-finally Mit try-with-resources

Die einfache und offensichtliche Möglichkeit, die neue Try-with-Resources- Funktionalität zu verwenden, besteht darin, den traditionellen und ausführlichen Try-Catch-finally- Block zu ersetzen .

Vergleichen wir die folgenden Codebeispiele - zuerst ein typischer Try-Catch-finally- Block, dann der neue Ansatz unter Verwendung eines äquivalenten Try-with-Resources-Blocks:

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(); } }

Und hier ist die super prägnante Lösung mit 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(); }

Hier können Sie die Scannerklasse weiter erkunden .

4. Versuchen Sie es mit Ressourcen mit mehreren Ressourcen

Mehrere Ressourcen können in einem Try-with-Resources- Block problemlos deklariert werden, indem sie durch ein Semikolon getrennt werden:

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. Eine benutzerdefinierte Ressource mit AutoCloseable

Um eine benutzerdefinierte Ressource zu erstellen, die von einem Try-with-Resources- Block korrekt behandelt wird , sollte die Klasse die Schnittstellen Closeable oder AutoCloseable implementieren und die Methode close überschreiben :

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

6. Ressourcenabschlussreihenfolge

Ressourcen, die zuerst definiert / erworben wurden, werden zuletzt geschlossen. Schauen wir uns ein Beispiel für dieses Verhalten an:

Ressource 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"); } } 

Ressource 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"); } }

Code:

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

Ausgabe:

Konstruktor -> AutoCloseableResources_First

Konstruktor -> AutoCloseableResources_Second

Etwas -> AutoCloseableResources_First

Etwas -> AutoCloseableResources_Second

AutoCloseableResources_Second geschlossen

AutoCloseableResources_First geschlossen

7. fangen & endlich

Ein Try-with-Resources- Block kann immer noch den Catch- und schließlich- Block haben - was genauso funktioniert wie bei einem herkömmlichen Try- Block.

8. Java 9: ​​Effektiv endgültigVariablen

Vor Java 9 konnten wir nur neue Variablen in einem Try-with-Resources- Block verwenden:

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

Wie oben gezeigt, war dies besonders ausführlich, wenn mehrere Ressourcen deklariert wurden. Ab Java 9 und als Teil von JEP 213 können wir jetzt endgültige oder sogar effektiv endgültige Variablen in einem Try-with-Resources- Block verwenden :

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

Einfach ausgedrückt ist eine Variable effektiv endgültig, wenn sie sich nach der ersten Zuweisung nicht ändert, obwohl sie nicht explizit als endgültig markiert ist .

Wie oben gezeigt, wird die Scannervariable explizit als final deklariert , sodass wir sie mit dem Block " Try-with-Resources " verwenden können. Obwohl die Writer- Variable nicht explizit endgültig ist, ändert sie sich nach der ersten Zuweisung nicht. Daher dürfen wir auch die Writer- Variable verwenden.

9. Fazit

In diesem Artikel haben wir erläutert, wie Sie Try-with-Resources verwenden, Try , Catch und schließlich Try-with-Resources ersetzen, benutzerdefinierte Ressourcen mit AutoCloseable erstellen und in welcher Reihenfolge Ressourcen geschlossen werden.

Der vollständige Quellcode für das Beispiel ist in diesem GitHub-Projekt verfügbar.