Menu
Coddy logo textTech

Pattern try-with-resources

Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 62 di 87.

Quando lavori con risorse come flussi di file o connessioni al database, devi sempre chiuderle quando hai finito. Altrimenti rischi perdite di memoria. L’approccio tradizionale usa un blocco finally, ma è prolisso e soggetto a errori.

L’istruzione try-with-resources di Java chiude automaticamente le risorse al termine del blocco. Qualsiasi classe che implementi l’interfaccia AutoCloseable può essere usata con questa sintassi:

// Approccio tradizionale - prolisso e rischioso
BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("file.txt"));
    String line = reader.readLine();
} finally {
    if (reader != null) {
        reader.close();  // Potrebbe anche generare un'eccezione!
    }
}

// Try-with-resources - semplice e sicuro
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
}  // Chiuso automaticamente qui

Puoi gestire più risorse separandole con punti e virgola. Vengono chiuse in ordine inverso rispetto alla dichiarazione:

try (FileReader fr = new FileReader("input.txt");
     BufferedReader br = new BufferedReader(fr)) {
    // Usa entrambe le risorse
}  // br viene chiuso per primo, poi fr

Per creare una tua classe con chiusura automatica, implementa l'interfaccia AutoCloseable e il suo unico metodo close():

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

Questo schema garantisce che le risorse vengano sempre rilasciate correttamente, anche se si verificano eccezioni durante l'elaborazione.

challenge icon

Sfida

Facile

Costruiamo un sistema di gestione delle risorse che dimostri la potenza di try-with-resources! Creerai classi personalizzate chiudibili automaticamente che simulano la gestione di connessioni e sessioni, assicurandoti che vengano sempre chiuse correttamente.

Organizzerai il codice in tre file:

  • Connection.java: Crea una classe che simuli una connessione a un database. La tua classe Connection deve implementare AutoCloseable. Deve avere un campo privato per il nome della connessione (String), un costruttore che accetta il nome e stampa [name] connection opened, un metodo query(String sql) che stampa Executing on [name]: [sql] e il metodo richiesto close() che stampa [name] connection closed.
  • Session.java: Crea un'altra classe chiudibile automaticamente che simuli una sessione utente. Anche la tua classe Session deve implementare AutoCloseable. Includi un campo privato per il nome utente (String), un costruttore che accetta il nome utente e stampa Session started for [username], un metodo performAction(String action) che stampa [username] performed: [action] e un metodo close() che stampa Session ended for [username].
  • Main.java: Metti insieme il tuo sistema di gestione delle risorse! Riceverai tre input: un nome di connessione, un nome utente e un'azione da eseguire.

    Per prima cosa, mostra la gestione di una singola risorsa. Stampa === Single Resource ===, quindi usa try-with-resources per creare una Connection con il nome fornito. All'interno del blocco try, chiama query("SELECT * FROM users"). La connessione dovrebbe chiudersi automaticamente al termine del blocco.

    Successivamente, mostra la gestione di più risorse. Stampa una riga vuota, quindi === Multiple Resources ===. Usa try-with-resources con una Connection (usando lo stesso nome) e una Session (usando il nome utente), dichiarate in quest'ordine e separate da punti e virgola. All'interno del blocco try, chiama prima query("INSERT INTO logs") sulla connessione, quindi chiama performAction sulla sessione usando l'azione inserita. Osserva come le risorse si chiudono in ordine inverso!

Riceverai tre input in quest'ordine: nome della connessione (String), nome utente (String) e azione (String).

Nota come try-with-resources elimina la necessità di chiamare esplicitamente close e di usare blocchi finally. È garantito che le risorse vengano chiuse anche se si verificano eccezioni, e le risorse multiple si chiudono in ordine inverso rispetto a quello della dichiarazione!

Provalo tu

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();
        
        // === Single Resource ===
        // TODO: Stampa l'intestazione
        // TODO: Usa try-with-resources per creare una Connection
        // TODO: All'interno del blocco try, chiama query("SELECT * FROM users")
        
        // === Multiple Resources ===
        // TODO: Stampa una riga vuota e l'intestazione
        // TODO: Usa try-with-resources sia con Connection sia con Session
        // TODO: All'interno del blocco try:
        //       - Chiama query("INSERT INTO logs") sulla connessione
        //       - Chiama performAction sulla sessione passando l'azione ricevuta in input
        
    }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Java online