Utilizzo di try e catch in Java

Concetti Chiave
  • La gestione delle eccezioni in Java consente di gestire errori e condizioni eccezionali in modo controllato.
  • Per gestire un'eccezione, si utilizza un blocco try per monitorare il codice e una clausola catch per intercettare l'eccezione.
  • Una volta che il controllo viene trasferito al blocco catch, il programma continua con la riga successiva dopo il blocco try / catch.
  • È possibile visualizzare una descrizione dell'eccezione utilizzando il metodo toString() dell'oggetto eccezione.

Utilizzo di try e catch

Anche se il gestore di eccezioni predefinito fornito dal sistema di esecuzione Java è utile per il debug, di solito si vorrà gestire un'eccezione autonomamente.

Questo fornisce due vantaggi. Primo, consente di correggere l'errore o quantomeno di reagire in modo appropriato. Ad esempio, se si verifica un errore di divisione per zero, è possibile impostare il risultato a zero o a un altro valore predefinito invece di terminare il programma. Questo è particolarmente importante in applicazioni che devono essere robuste e resistenti agli errori.

Secondo, impedisce al programma di terminare automaticamente. La maggior parte degli utenti sarebbe confusa (per usare un eufemismo) se il programma si interrompesse stampando una traccia dello stack ogni volta che si verifica un errore! Fortunatamente, è abbastanza facile prevenire ciò.

Per proteggersi e gestire un errore a tempo di esecuzione, è sufficiente racchiudere il codice che si desidera monitorare all'interno di un blocco try.

Immediatamente dopo il blocco try, includere una clausola catch che specifica il tipo di eccezione che si desidera intercettare.

Per illustrare quanto sia semplice farlo, il programma seguente include un blocco try e una clausola catch che gestisce l'eccezione ArithmeticException generata dall'errore di divisione per zero:

class Esec2 {
    public static void main(String[] args) {
        int d, a;

        try {
            // monitora un blocco di codice.
            d = 0;
            a = 42 / d;
            System.out.println("Questo non verrà stampato.");
        } catch (ArithmeticException e) {
            // intercetta errore di divisione per zero
            System.out.println("Divisione per zero.");
        }
        System.out.println("Dopo l'istruzione catch.");
    }
}

Questo programma genera il seguente output:

Divisione per zero.
Dopo l'istruzione catch.

Notare che la chiamata a println() all'interno del blocco try non viene mai eseguita.

Una volta che un'eccezione viene generata, il controllo del programma viene trasferito fuori dal blocco try nel blocco catch.

In altre parole, catch non viene "chiamato", quindi l'esecuzione non "ritorna" mai al blocco try da un catch. Pertanto, la riga "Questo non verrà stampato." non viene visualizzata. Una volta eseguita l'istruzione catch, il controllo del programma continua con la riga successiva nel programma dopo l'intero meccanismo try / catch.

Un try e il suo catch formano un'unità. L'ambito della clausola catch è limitato solo a quelle istruzioni specificate dalla dichiarazione try immediatamente precedente.

Una clausola catch non può intercettare un'eccezione generata da un'altra istruzione try (eccetto nel caso di istruzioni try annidate, descritte in seguito). Le istruzioni protette da try devono essere racchiuse tra parentesi graffe. (Cioè, devono trovarsi all'interno di un blocco.) Non è possibile utilizzare try su una sola istruzione.

L'obiettivo della maggior parte delle clausole catch ben costruite dovrebbe essere quello di risolvere la condizione eccezionale e poi continuare come se l'errore non fosse mai avvenuto.

Per esempio, nel programma seguente, ogni iterazione del ciclo for ottiene due interi casuali. Questi due interi vengono divisi tra loro, e il risultato viene utilizzato per dividere il valore 12345. Il risultato finale viene assegnato a a. Se l'operazione di divisione genera un errore di divisione per zero, viene intercettato, il valore di a viene impostato a zero, e il programma continua.

// Gestisce un'eccezione e continua.
import java.util.Random;

class GestioneErrore {
    public static void main(String[] args) {
        int a=0, b=0, c=0;
        Random r = new Random();

        for(int i=0; i<32000; i++) {
            try {
                b = r.nextInt();
                c = r.nextInt();
                a = 12345 / (b/c);
            } catch (ArithmeticException e) {
                System.out.println("Divisione per zero.");
                a = 0; // imposta a a zero e continua
            }
            System.out.println("a: " + a);
        }
    }
}

Visualizzare una Descrizione di un'Eccezione

Throwable sovrascrive il metodo toString() (definito da Object) in modo tale da restituire una stringa contenente una descrizione dell'eccezione.

È possibile visualizzare questa descrizione in un'istruzione println() semplicemente passando l'eccezione come argomento. Per esempio, il blocco catch nel programma precedente può essere riscritto in questo modo:

catch (ArithmeticException e) {
    System.out.println("Eccezione: " + e);
    a = 0; // imposta a zero e continua
}

Quando questa versione viene sostituita nel programma, ed esso viene eseguito, ogni errore di divisione per zero visualizza il seguente messaggio:

Eccezione: java.lang.ArithmeticException: / by zero

Mentre non ha particolare valore in questo contesto, la capacità di visualizzare una descrizione di un'eccezione è utile in altre circostanze—specialmente quando si sta sperimentando con le eccezioni o durante il debug.