So verwenden Sie Try With Resource in Java

Feb 21 2023
So behandeln Sie Ausnahmen mithilfe der Try-with-Resource-Anweisung. Das Java-Konstrukt „Try with Resources“, auch Java Try-with-Resources genannt, ist ein Ausnahmebehandlungsmechanismus, der Ressourcen wie einen Java InputStream oder eine JDBC-Verbindung automatisch schließen kann, wenn Sie mit ihnen fertig sind . Oracle hat 2011 das Try-with-Resources-Konstrukt zur Java-Sprache hinzugefügt, um sicherzustellen, dass Objekte wie Netzwerk-Sockets, Datenbankverbindungen und Verweise auf Dateien und Ordner nach ihrer Verwendung sauber beendet werden.

So behandeln Sie Ausnahmen mithilfe der try-with-resource-Anweisung

Das Java- Try-with-Resources- Konstrukt, auch bekannt als Java try-with-resources , ist ein Ausnahmebehandlungsmechanismus, der Ressourcen wie einen Java InputStream oder eine JDBC-Verbindung automatisch schließen kann, wenn Sie mit ihnen fertig sind.

Oracle hat 2011 das Try-with-Resources-Konstrukt zur Java-Sprache hinzugefügt, um sicherzustellen, dass Objekte wie Netzwerk-Sockets, Datenbankverbindungen und Verweise auf Dateien und Ordner nach ihrer Verwendung sauber beendet werden. Wenn diese Ressourcen nicht geschlossen werden, nachdem ein Entwickler ein Handle für sie geöffnet hat, kann dies zu Speicherverlusten führen , vermeidbare Garbage-Collection-Routinen auslösen und die CPU eines Servers belasten .

· Vor Java 7
· Wie verwende ich die Try-with-Resource-Anweisung?
· Warum muss ich die Try-with-Resource-Anweisung verwenden?
· Beispiel
· Unterdrückte Ausnahmen
· Vorteile der Verwendung von „try-with-resources“
· „try-with-resources mit mehreren Ressourcen“
· Java 9 – Effektiv endgültige Variablen

Vor Java 7

Wenn Sie in Java eine Ressource wie Eingabe- oder Ausgabestreams verwenden, müssen Sie diese nach der Verwendung immer schließen. Es kann auch Ausnahmen auslösen, daher muss es sich in einem Try-Catch- Block befinden. Der Abschluss muss im „finally “-Block erfolgen. Dies war zumindest bis Java 7 der Fall. Dies hat mehrere Nachteile:

  • Sie müssten prüfen, ob Ihre Ressource null ist , bevor Sie sie schließen
  • Das Schließen selbst kann Ausnahmen auslösen, sodass Sie schließlich einen weiteren Try-Catch enthalten mussten
  • Programmierer neigen dazu, zu vergessen, ihre Ressourcen zu schließen

Wie verwende ich die Try-with-Resource-Anweisung?

Es wurde ursprünglich in Java 7 eingeführt und die Grundidee dahinter bestand darin, dass sich der Entwickler keine Gedanken über die Ressourcenverwaltung für Ressourcen machen muss, die er nur in einem Try- Catch-Finally- Block verwendet . Dies wird erreicht, indem die Notwendigkeit von „finally“ -Blöcken entfällt , die Entwickler in der Praxis nur zum Schließen von Ressourcen verwendeten.

In Java ist die try-with-resources-Anweisung eine try-Anweisung, die eine oder mehrere Ressourcen deklariert. Die Ressource ist ein Objekt, das nach Beendigung des Programms geschlossen werden muss. Wenn die Ausführung den Try-with-Resources- Block verlässt, wird jede innerhalb des Try-with-Resources- Blocks geöffnete Ressource automatisch geschlossen, unabhängig davon, ob Ausnahmen entweder innerhalb des Try-with-Resources- Blocks oder beim Versuch, ihn zu schließen, ausgelöst werden die Ressourcen.

Um die Sprachfunktion „Try-with-Ressourcen“ von Java zu verwenden, gelten die folgenden Regeln:

  • Alle von einer try with resources-Anweisung verwalteten Objekte müssen die AutoCloseable-Schnittstelle implementieren.
  • Innerhalb des Try with Resources-Blocks von Java können mehrere AutoCloseable-Objekte erstellt werden.
  • Objekte, die in einer try with resources-Anweisung deklariert werden, haben einen Gültigkeitsbereich innerhalb des try-Blocks, jedoch nicht innerhalb der Blöcke „catch“ und „finally“.
  • Die Methode close() von Objekten, die in einem Block „try with resources“ deklariert werden, wird unabhängig davon aufgerufen, ob während der Ausführung eine Ausnahme ausgelöst wird.
  • Wenn in der Methode close() eine Ausnahme ausgelöst wird, wird sie möglicherweise als unterdrückte Ausnahme kategorisiert .

Die vom AutoCloseable-Objekt referenzierte Ressource wird immer geschlossen, wenn eine try with resources-Anweisung verwendet wird, und potenzielle Speicherlecks, die häufig durch eine Fehlzuweisung von Ressourcen verursacht werden, werden beseitigt.

Syntax

try(declare resources here) {
    // use resources
}
catch(FileNotFoundException e) {
    // exception handling
}

Einfach ausgedrückt muss eine Ressource zum automatischen Schließen sowohl im try deklariert als auch initialisiert werden :

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

Der einfache und offensichtliche Weg, die neue Try-with-Resources- Funktionalität zu nutzen, besteht darin, den traditionellen und ausführlichen Try-Catch-Finally- Block zu ersetzen.

Vergleichen wir die folgenden Codebeispiele.

Der erste ist ein typischer Try-Catch-Finally -Block:

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();
    }
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

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

Wenn es um Ausnahmen geht, gibt es einen Unterschied zwischen dem Try-Catch-Finally- Block und dem Try-with-Resources-Block. Wenn sowohl im Try-Block als auch im Final-Block eine Ausnahme ausgelöst wird, gibt die Methode die im Final-Block ausgelöste Ausnahme zurück.

Wenn bei Try-with-Resources eine Ausnahme in einem Try-Block und in einer Try-with-Resources-Anweisung ausgelöst wird, gibt die Methode die im Try-Block ausgelöste Ausnahme zurück. Die von try-with-resources ausgelösten Ausnahmen werden unterdrückt, d. h. wir können sagen, dass der try-with-resources-Block unterdrückte Ausnahmen auslöst.

Warum muss ich die Try-with-Resource-Anweisung verwenden?

Die try-with-resources-Anweisung stellt sicher, dass jede Ressource am Ende der Anweisungsausführung geschlossen wird . Wenn wir die Ressourcen nicht schließen, kann es zu einem Ressourcenleck kommen und außerdem könnte das Programm die ihm zur Verfügung stehenden Ressourcen erschöpfen. Das passiert meistens, wenn Sie den Try-Catch-Finally- Block verwenden

Vor Java SE 7 können Sie einen „final“ -Block verwenden, um sicherzustellen, dass eine Ressource geschlossen wird, unabhängig davon, ob die try- Anweisung normal oder abrupt abgeschlossen wird. Im folgenden Beispiel wird ein „finally “-Block anstelle einer „try -with-resources“-Anweisung verwendet:

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
   
    FileReader fr = new FileReader(path);
    BufferedReader br = new BufferedReader(fr);
    try {
        return br.readLine();
    } finally {
        br.close();
        fr.close();
    }
}

Wenn in diesem Beispiel die Methode „readLine“ eine Ausnahme auslöst und die Anweisung „ br.close()“ im „ finally “-Block eine Ausnahme auslöst, ist der FileReader durchgesickert. Verwenden Sie daher eine try -with-resources-Anweisung anstelle eines „finally“ -Blocks, um die Ressourcen Ihres Programms zu schließen.

Beispiel

Das folgende Beispiel liest die erste Zeile aus einer Datei. Es verwendet eine Instanz von FileReader und BufferedReader , um Daten aus der Datei zu lesen. FileReader und BufferedReader sind Ressourcen, die geschlossen werden müssen, nachdem das Programm damit fertig ist:

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

Unterdrückte Ausnahmen

Wenn ein Try-Block eine Ausnahme auslöst und eine oder mehrere Ausnahmen von Try-with-Resources ausgelöst werden, werden die von Try-with-Resources ausgelösten Ausnahmen unterdrückt. Mit anderen Worten können wir sagen, dass Ausnahmen, die durch try-with-resources ausgelöst werden, unterdrückte Ausnahmen sind.

Sie können diese Ausnahmen erhalten, indem Sie die Methode getSuppress() der Klasse Throwable verwenden.

Beispiel :

Im obigen Beispiel können Ausnahmen von der try-with-resources -Anweisung ausgelöst werden, wenn:

  • Die Datei test.txt wurde nicht gefunden.
  • Schließen des BufferedReader- Objekts.

Wenn Ausnahmen sowohl vom try- Block als auch von der try -with-resources- Anweisung ausgelöst werden, wird eine Ausnahme vom try -Block ausgelöst und die Ausnahme von der try-with-resources- Anweisung unterdrückt.

Unterdrückte Ausnahmen abrufen

In Java 7 und höher können die unterdrückten Ausnahmen abgerufen werden, indem die Methode Throwable.getSuppressed() aus der vom try- Block ausgelösten Ausnahme aufgerufen wird .

getSuppress() Gibt ein Array zurück, das alle Ausnahmen enthält, die durch die try-with-resources-Anweisung unterdrückt wurden. Wenn keine Ausnahmen unterdrückt wurden oder die Unterdrückung deaktiviert ist, wird ein leeres Array zurückgegeben.

Die unterdrückten Ausnahmen erhalten wir im Catch- Block.

catch(IOException e) {
  System.out.println("Thrown exception=>" + e.getMessage());
  Throwable[] suppressedExceptions = e.getSuppressed();
  for (int i=0; i<suppressedExceptions.length; i++) {
    System.out.println("Suppressed exception=>" + suppressedExceptions[i]);
  }
}

Hier sind die Vorteile der Verwendung von Try-with-Resources:

  • Besser lesbarer Code und einfacher zu schreiben.
  • Automatisches Ressourcenmanagement.
  • Die Anzahl der Codezeilen wird reduziert.
  • Wenn in try-with-resources mehrere Ressourcen geöffnet werden, werden sie in umgekehrter Reihenfolge geschlossen, um Abhängigkeitsprobleme zu vermeiden.

Bevor Java 7 diese Funktion einführte, mussten wir den „finally“ -Block verwenden, um sicherzustellen, dass die Ressource geschlossen ist, um Ressourcenlecks zu vermeiden.

Hier ist ein Programm, das Beispiel 1 ähnelt . In diesem Programm haben wir jedoch „finally block“ zum Schließen von Ressourcen verwendet.

Beispiel: Ressource mit dem Block „finally“ schließen

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

Entering try block
Line =>line from test.txt file
Entering finally block

Ist Ihnen auch der try…catch -Block im „finally“ -Block aufgefallen? Dies liegt daran, dass beim Schließen der BufferedReader- Instanz innerhalb dieses „finally“ -Blocks auch eine IOException auftreten kann, sodass sie ebenfalls abgefangen und behandelt wird.

Die try-with-resources- Anweisung führt eine automatische Ressourcenverwaltung durch . Wir müssen die Ressourcen nicht explizit schließen, da JVM sie automatisch schließt. Dadurch wird der Code besser lesbar und einfacher zu schreiben.

Try-with-Ressourcen mit mehreren Ressourcen

Wir können problemlos mehrere Ressourcen in einem try-with-resources -Block deklarieren, indem wir sie durch ein Semikolon trennen:

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

Vor Java 9 konnten wir neue Variablen nur innerhalb eines Try-with-Resources- Blocks verwenden:

try (Scanner scanner = new Scanner(new File("testRead.txt")); 
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

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

Viel Spaß beim Lernen

Treten Sie der Mouad Oumous Java WhatsApp-Gruppe bei

Treten Sie dem Telegram-Kanal von Mouad Oumous bei

Unterstützen Sie unsere Publikation, indem Sie ihr folgen

Leitfaden zur Objektzuordnung mit ModelMapper in Java Erste Schritte mit Spring Boot: Ein umfassendes Tutorial für Anfänger Spring Boot-Sicherheit | SSO | OAuth2 mit Okta Am häufigsten gestellte Frage im Interview mit Java8 Stream – Teil 2 Codierung: Reduzieren Sie ein Array in Javascript. Am häufigsten gestellte Frage im Interview mit Java8 Stream – Teil 1