Come usare Prova con la risorsa in Java

Feb 21 2023
Come gestire le eccezioni usando l'istruzione try-with-resource Il costrutto Java try with resources, AKA Java try-with-resources, è un meccanismo di gestione delle eccezioni che può chiudere automaticamente risorse come un Java InputStream o una connessione JDBC quando hai finito con loro . Oracle ha aggiunto il costrutto try with resources al linguaggio Java nel 2011 per aiutare a garantire che oggetti come socket di rete, connessioni al database e riferimenti a file e cartelle vengano terminati in modo pulito dopo il loro utilizzo.

Come gestire le eccezioni usando l'istruzione try-with-resource

Il costrutto Java try with resources , AKA Java try-with-resources , è un meccanismo di gestione delle eccezioni che può chiudere automaticamente risorse come un Java InputStream o una connessione JDBC quando hai finito con loro.

Oracle ha aggiunto il costrutto try with resources al linguaggio Java nel 2011 per aiutare a garantire che oggetti come socket di rete, connessioni al database e riferimenti a file e cartelle vengano terminati in modo pulito dopo il loro utilizzo. La mancata chiusura di queste risorse dopo che uno sviluppatore ne ha aperto un handle può causare perdite di memoria , attivare routine di garbage collection evitabili e sovraccaricare la CPU di un server .

· Prima di Java 7
· Come utilizzare l'istruzione try-with-resource?
· Perché devo usare l'istruzione try-with-resource?
· Esempio
· Eccezioni soppresse
· Vantaggi dell'utilizzo di try-with-resources
· try-with-resources con più risorse
· Java 9 — Variabili effettivamente finali

Prima di Java 7

In Java, se usi una risorsa come flussi di input o output, devi sempre chiuderla dopo averla utilizzata. Può anche generare eccezioni, quindi deve trovarsi in un blocco try-catch . La chiusura deve essere nel blocco finale . Questo è almeno il modo fino a Java 7. Questo ha diversi svantaggi:

  • Dovresti verificare se la tua risorsa è nulla prima di chiuderla
  • La chiusura stessa può generare eccezioni, quindi alla fine hai dovuto contenere un altro try-catch
  • I programmatori tendono a dimenticare di chiudere le proprie risorse

Come utilizzare l'istruzione try-with-resource?

Inizialmente è stato introdotto in Java 7 e l'idea alla base era che lo sviluppatore non deve preoccuparsi della gestione delle risorse per le risorse che utilizza solo in un blocco try-catch-finally . Ciò si ottiene eliminando la necessità di blocchi finally , che gli sviluppatori utilizzavano solo per chiudere le risorse in pratica.

In Java, l'istruzione try-with-resources è un'istruzione try che dichiara una o più risorse. La risorsa è come un oggetto che deve essere chiuso al termine del programma. Quando l'esecuzione lascia il blocco try-with-resources , qualsiasi risorsa aperta all'interno del blocco try-with-resources viene chiusa automaticamente, indipendentemente dal fatto che vengano lanciate eccezioni dall'interno del blocco try-with-resources o durante il tentativo di chiusura le risorse.

Per utilizzare la funzione del linguaggio try-with-resources di Java, si applicano le seguenti regole:

  • Tutti gli oggetti gestiti da un'istruzione try with resources devono implementare l'interfaccia AutoCloseable.
  • È possibile creare più oggetti AutoCloseable all'interno del blocco try with resources di Java.
  • Gli oggetti dichiarati in un'istruzione try with resources hanno un ambito all'interno del blocco try, ma non i blocchi catch e finally.
  • Il metodo close() degli oggetti dichiarati in un blocco try with resources viene richiamato indipendentemente dal fatto che durante l'esecuzione venga generata un'eccezione.
  • Se viene generata un'eccezione nel metodo close(), potrebbe essere classificata come eccezione soppressa .

La risorsa a cui fa riferimento l'oggetto AutoCloseable verrà sempre chiusa se viene utilizzata un'istruzione try with resources e vengono eliminate potenziali perdite di memoria comunemente causate da un'allocazione errata delle risorse.

Sintassi

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

In poche parole, per essere chiusa automaticamente, una risorsa deve essere sia dichiarata che inizializzata all'interno del try :

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

Il modo semplice e ovvio per utilizzare la nuova funzionalità try-with-resources è sostituire il tradizionale e prolisso blocco try-catch-finally .

Confrontiamo i seguenti esempi di codice.

Il primo è un tipico blocco try-catch-finally :

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

Quando si tratta di eccezioni, c'è una differenza nel blocco try-catch-finally e nel blocco try-with-resources. Se viene generata un'eccezione sia in try block che in finally block, il metodo restituisce l'eccezione generata in finally block.

Per try-with-resources, se viene generata un'eccezione in un blocco try e in un'istruzione try-with-resources, il metodo restituisce l'eccezione generata nel blocco try. Le eccezioni lanciate da try-with-resources sono soppresse, cioè possiamo dire che il blocco try-with-resources genera eccezioni soppresse.

Perché devo usare l'istruzione try-with-resource?

L'istruzione try-with-resources assicura che ogni risorsa sia chiusa alla fine dell'esecuzione dell'istruzione . Se non chiudiamo le risorse, potrebbe costituire una perdita di risorse e anche il programma potrebbe esaurire le risorse a sua disposizione. questo è quello che è successo soprattutto quando usi il blocco try-catch-finally

Prima di Java SE 7, puoi utilizzare un blocco finally per assicurarti che una risorsa venga chiusa indipendentemente dal fatto che l' istruzione try venga completata normalmente o bruscamente. L'esempio seguente utilizza un blocco finally invece di un'istruzione try -with-resources:

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

In questo esempio, se il metodo readLine genera un'eccezione e l'istruzione br.close() nel blocco finally genera un'eccezione, allora il FileReader è trapelato. Pertanto, usa un'istruzione try -with-resources invece di un blocco finally per chiudere le risorse del tuo programma.

Esempio

L'esempio seguente legge la prima riga da un file. Utilizza un'istanza di FileReader e BufferedReader per leggere i dati dal file. FileReader e BufferedReader sono risorse che devono essere chiuse al termine del programma:

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

Eccezioni soppresse

Se un blocco try genera un'eccezione e una o più eccezioni vengono generate da try-with-resources, le eccezioni generate da try-with-resources vengono soppresse. In altre parole, possiamo dire che le eccezioni lanciate da try-with-resources sono eccezioni soppresse.

Puoi ottenere queste eccezioni usando il metodo getSuppress() della classe Throwable.

Esempio :

Nell'esempio precedente, le eccezioni possono essere generate dall'istruzione try-with-resources quando:

  • Il file test.txt non è stato trovato.
  • Chiusura dell'oggetto BufferedReader .

Se le eccezioni vengono lanciate sia dal blocco try che dall'istruzione try-with-resources , viene generata un'eccezione dal blocco try e l'eccezione dall'istruzione try-with-resources viene soppressa.

Recupero delle eccezioni soppresse

In Java 7 e versioni successive, le eccezioni soppresse possono essere recuperate chiamando il metodo Throwable.getSuppressed() dall'eccezione generata dal blocco try .

getSuppress() Restituisce un array contenente tutte le eccezioni soppresse dall'istruzione try-with-resources. Se non sono state soppresse eccezioni o se la soppressione è disabilitata, viene restituito un array vuoto.

Otteniamo le eccezioni soppresse nel blocco catch .

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

Ecco i vantaggi dell'utilizzo di try-with-resources:

  • Codice più leggibile e facile da scrivere.
  • Gestione automatica delle risorse.
  • Il numero di righe di codice è ridotto.
  • Quando più risorse vengono aperte in try-with-resources, le chiude nell'ordine inverso per evitare qualsiasi problema di dipendenza.

Prima che Java 7 introducesse questa funzionalità, dovevamo utilizzare il blocco finally per assicurarci che la risorsa fosse chiusa per evitare perdite di risorse.

Ecco un programma simile all'Esempio 1 . Tuttavia, in questo programma, abbiamo utilizzato infine il blocco per chiudere le risorse.

Esempio: chiudere la risorsa utilizzando finally block

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

Notate anche il blocco try…catch nel blocco finally ? Questo perché può verificarsi anche un'eccezione IOException durante la chiusura dell'istanza BufferedReader all'interno di questo blocco finally , quindi viene anch'essa rilevata e gestita.

L' istruzione try-with-resources esegue la gestione automatica delle risorse . Non è necessario chiudere esplicitamente le risorse poiché JVM le chiude automaticamente. Ciò rende il codice più leggibile e più facile da scrivere.

try-with-resources Con più risorse

Possiamo dichiarare bene più risorse in un blocco try-with-resources separandole con un punto e virgola:

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

Prima di Java 9, potevamo usare solo nuove variabili all'interno di un blocco try-with-resources :

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

Come mostrato sopra, la variabile scanner è dichiarata final in modo esplicito, quindi possiamo usarla con il blocco try-with-resources . Sebbene la variabile writer non sia esplicitamente final, non cambia dopo la prima assegnazione. Quindi, possiamo usare anche la variabile writer .

Buon apprendimento

Unisciti al gruppo Mouad Oumous Java WhatsApp ISCRIVITI

Unisciti al canale Telegram di Mouad Oumous ISCRIVITI

Sostieni la nostra pubblicazione seguendola

Guida alla mappatura degli oggetti con ModelMapper in Java Introduzione a Spring Boot: un tutorial completo per principianti Spring Boot Security | SO | OAuth2 con Okta Domanda di intervista basata sul flusso Java8 più frequente - Parte 2 Codifica: appiattisci un array in Javascript Domanda di intervista basata sul flusso Java8 più comunemente richiesta - Parte 1