Menu
Coddy logo textTech

Try-With-Resources-Pattern

Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 62 von 87.

Beim Arbeiten mit Ressourcen wie Dateiströmen oder Datenbankverbindungen müssen Sie diese nach Abschluss immer schließen – andernfalls riskieren Sie Speicherlecks. Der herkömmliche Ansatz verwendet einen finally-Block, ist jedoch wortreich und fehleranfällig.

Javas try-with-resources-Anweisung schließt Ressourcen automatisch, wenn der Block abgeschlossen ist. Jede Klasse, die das AutoCloseable-Interface implementiert, kann mit dieser Syntax verwendet werden:

// Traditioneller Ansatz - wortreich und riskant
BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("file.txt"));
    String line = reader.readLine();
} finally {
    if (reader != null) {
        reader.close();  // Könnte ebenfalls eine Exception auslösen!
    }
}

// Try-with-resources - sauber und sicher
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
}  // Wird hier automatisch geschlossen

Sie können mehrere Ressourcen verwalten, indem Sie diese durch Semikolons trennen. Sie werden in umgekehrter Reihenfolge ihrer Deklaration geschlossen:

try (FileReader fr = new FileReader("input.txt");
     BufferedReader br = new BufferedReader(fr)) {
    // Beide Ressourcen verwenden
}  // br wird zuerst geschlossen, dann fr

Um Ihre eigene auto-closeable Klasse zu erstellen, implementieren Sie das AutoCloseable Interface und dessen einzelne close() Methode:

public class DatabaseConnection implements AutoCloseable {
    public DatabaseConnection() {
        System.out.println("Connection opened");
    }
    
    @Override
    public void close() {
        System.out.println("Connection closed");
    }
}

Dieses Muster stellt sicher, dass Ressourcen immer ordnungsgemäß freigegeben werden, selbst wenn während der Verarbeitung Ausnahmen auftreten.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Ressourcenmanagementsystem bauen, das die Leistungsfähigkeit von try-with-resources demonstriert! Sie werden benutzerdefinierte auto-closeable Klassen erstellen, die das Verwalten von Verbindungen und Sitzungen simulieren und sicherstellen, dass diese immer ordnungsgemäß bereinigt werden.

Sie werden Ihren Code über drei Dateien organisieren:

  • Connection.java: Erstellen Sie eine Klasse, die eine Datenbankverbindung simuliert. Ihre Connection-Klasse sollte AutoCloseable implementieren. Sie benötigt ein privates Feld für den Verbindungsnamen (String), einen Konstruktor, der den Namen entgegennimmt und [name] connection opened ausgibt, eine query(String sql)-Methode, die Executing on [name]: [sql] ausgibt, und die erforderliche close()-Methode, die [name] connection closed ausgibt.
  • Session.java: Erstellen Sie eine weitere auto-closeable Klasse, die eine Benutzersitzung simuliert. Ihre Session-Klasse sollte ebenfalls AutoCloseable implementieren. Fügen Sie ein privates Feld für den Benutzernamen (String) hinzu, einen Konstruktor, der den Benutzernamen entgegennimmt und Session started for [username] ausgibt, eine performAction(String action)-Methode, die [username] performed: [action] ausgibt, und eine close()-Methode, die Session ended for [username] ausgibt.
  • Main.java: Bringen Sie Ihr Ressourcenmanagementsystem zusammen! Sie erhalten drei Eingaben: einen Verbindungsnamen, einen Benutzernamen und eine auszuführende Aktion.

    Demonstrieren Sie zuerst das Management einer einzelnen Ressource. Geben Sie === Single Resource === aus und verwenden Sie dann try-with-resources, um eine Connection mit dem angegebenen Namen zu erstellen. Rufen Sie innerhalb des try-Blocks query("SELECT * FROM users") auf. Die Verbindung sollte automatisch geschlossen werden, wenn der Block endet.

    Demonstrieren Sie als Nächstes mehrere Ressourcen. Geben Sie eine Leerzeile aus, dann === Multiple Resources ===. Verwenden Sie try-with-resources sowohl mit einer Connection (unter Verwendung desselben Namens) als auch mit einer Session (unter Verwendung des Benutzernamens), die in dieser Reihenfolge mit Semikolons deklariert werden. Rufen Sie innerhalb des try-Blocks zuerst query("INSERT INTO logs") auf der Verbindung auf und rufen Sie dann performAction mit der eingegebenen Aktion auf der Sitzung auf. Beobachten Sie, wie Ressourcen in umgekehrter Reihenfolge geschlossen werden!

Sie erhalten drei Eingaben in der folgenden Reihenfolge: Verbindungsname (String), Benutzername (String) und Aktion (String).

Beachten Sie, wie try-with-resources die Notwendigkeit expliziter close-Aufrufe und finally-Blöcke eliminiert. Es ist garantiert, dass die Ressourcen geschlossen werden, selbst wenn Ausnahmen auftreten, und mehrere Ressourcen werden in umgekehrter Deklarationsreihenfolge geschlossen!

Spickzettel

Die try-with-resources-Anweisung schließt Ressourcen automatisch, wenn der Block abgeschlossen ist. Jede Klasse, die AutoCloseable implementiert, kann verwendet werden:

try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
}  // Wird hier automatisch geschlossen

Mehrere Ressourcen können verwaltet werden, indem sie durch Semikolons getrennt werden. Sie werden in umgekehrter Reihenfolge der Deklaration geschlossen:

try (FileReader fr = new FileReader("input.txt");
     BufferedReader br = new BufferedReader(fr)) {
    // Beide Ressourcen verwenden
}  // br wird zuerst geschlossen, dann fr

Um eine benutzerdefinierte Auto-Closeable-Klasse zu erstellen, implementieren Sie das AutoCloseable-Interface und dessen close()-Methode:

public class DatabaseConnection implements AutoCloseable {
    public DatabaseConnection() {
        System.out.println("Connection opened");
    }
    
    @Override
    public void close() {
        System.out.println("Connection closed");
    }
}

Probier es selbst

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String connectionName = scanner.nextLine();
        String username = scanner.nextLine();
        String action = scanner.nextLine();
        
        // === Einzelne Ressource ===
        // TODO: Den Header ausgeben
        // TODO: try-with-resources verwenden, um eine Connection zu erstellen
        // TODO: Innerhalb des try-Blocks query("SELECT * FROM users") aufrufen
        
        // === Mehrere Ressourcen ===
        // TODO: Eine Leerzeile und den Header ausgeben
        // TODO: try-with-resources sowohl mit Connection als auch mit Session verwenden
        // TODO: Innerhalb des try-Blocks:
        //       - query("INSERT INTO logs") auf der Connection aufrufen
        //       - performAction mit der Eingabe action auf der Session aufrufen
        
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung