Il linguaggio di programmazione Java usa le eccezioni per gestire gli errori e altri eventi eccezionali.
Un'eccezione è un evento che si verifica durante l'esecuzione di un programma e che interrompe il normale flusso delle istruzioni. In Java le eccezioni vengono lanciate esplicitamente, e l'atto di lanciare un'eccezione si chiama lanciare un'eccezione. L'atto di gestire un'eccezione si chiama catturare un'eccezione.
In Java, tutte le eccezioni sono sottoclassi della classe Exception, che a sua volta è una sottoclasse di Throwable.
Java distingue due tipi di eccezioni:
Le eccezioni controllate sono condizioni eccezionali che un'applicazione dovrebbe prevedere e dalle quali dovrebbe riprendersi.
Un esempio di eccezione controllata è la FileNotFoundException, che si verifica quando un metodo prova a leggere un file che non esiste.
Questo tipo di eccezione viene controllato in fase di compilazione: i metodi che lanciano eccezioni controllate devono specificarlo nella loro firma, e il codice che chiama un metodo che potrebbe lanciare un'eccezione controllata deve gestirla, altrimenti non verrà compilato.
Tutte le eccezioni controllate sono sottoclassi di Exception che non estendono RuntimeException.
Le eccezioni non controllate sono condizioni eccezionali che un'applicazione di solito non può prevedere e dalle quali non può riprendersi.
Un esempio di eccezione non controllata è la NullPointerException, che si verifica quando un metodo si aspetta un valore non nullo ma riceve null.
Questo tipo di eccezione non viene controllato in fase di compilazione: i metodi che lanciano eccezioni non controllate non sono tenuti a specificarlo nella loro firma, e il codice che chiama un metodo che potrebbe lanciare un'eccezione non controllata non è tenuto a gestirla.
Tutte le eccezioni non controllate derivano da RuntimeException, che a sua volta è un'estensione di Exception.
Un metodo in Java può lanciare un'eccezione usando l'istruzione throw.
Quando si lancia un'eccezione controllata da un metodo, è necessario specificarlo nella firma del metodo usando la parola chiave throws, come mostra l'esempio seguente.
Questo obbliga il codice chiamante a prevedere che un'eccezione potrebbe essere lanciata e a gestirla di conseguenza.
public class InsufficientBalanceException extends Exception {
}
public class BankAccount {
public void withdraw(double amount) throws InsufficientBalanceException {
if (balance < amount) {
throw new InsufficientBalanceException();
}
// rest of the method implementation
}
}
Quando si lancia un'eccezione non controllata da un metodo, non è necessario specificarlo nella firma del metodo, anche se è supportato.
public class BankAccount {
public void withdraw(double amount) {
if (amount < 0) {
throw new IllegalArgumentException("Cannot withdraw a negative amount");
}
// rest of the method implementation
}
}
In Java la gestione delle eccezioni si fa con le parole chiave try, catch e finally.
try.try è seguito da uno o più blocchi catch che catturano le eccezioni lanciate nel blocco try.catch possono essere seguiti facoltativamente da un blocco finally che viene sempre eseguito dopo il blocco try, indipendentemente dal fatto che sia stata lanciata o meno un'eccezione.L'esempio seguente mostra come funzionano queste parole chiave:
public class ATM {
public void withdraw(BankAccount bankAccount, double amount) {
try {
System.out.println("Withdrawing " + amount);
bankAccount.withdraw(amount);
System.out.println("Withdrawal succeeded");
} catch (InsufficientBalanceException) {
System.out.println("Withdrawal failed: insufficient balance");
} catch (RuntimeException e) {
System.out.println("Withdrawal failed: " + e.getMessage());
} finally {
System.out.println("Current balance: " + bankAccount.getBalance());
}
}
}
In questo esempio, quando non viene lanciata alcuna eccezione, viene stampato quanto segue:
Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0
Se invece l'istruzione bankAccount.withdraw(amount) lancia una InsufficientBalanceException, viene stampato quanto segue:
Withdrawing 10.0
Withdrawal failed: insufficient balance
Current balance: 5.0
Oppure, se bankAccount.withdraw(amount) lancia un'eccezione non controllata, viene stampato quanto segue:
Withdrawing -10.0
Withdrawal failed: Cannot withdraw a negative amount
Current balance: 5.0
Java ha anche una categoria separata chiamata Errors, che sono problemi seri ed esterni a un'applicazione.
Un esempio di errore è OutOfMemoryError, che si verifica quando un'applicazione prova a usare più memoria di quanta ne sia disponibile nel sistema.
Come le eccezioni non controllate, gli errori non vengono controllati in fase di compilazione. La differenza è che rappresentano problemi a livello di sistema e di solito vengono lanciati dalla Java Virtual Machine o dall'ambiente invece che dall'applicazione. In generale, le applicazioni non dovrebbero cercare di catturarli o gestirli.
Tutti gli errori in Java derivano dalla classe Error.
Come detto in precedenza, le eccezioni sono eventi che interrompono il normale flusso delle istruzioni e servono a gestire gli eventi eccezionali. Per questo, nella tua applicazione non è consigliabile usare le eccezioni per controllare il flusso.