1. Introduzione alle eccezioni
Cominciamo con una semplice analogia. Immaginate che il vostro programma — sia un’auto che percorre una strada. Tutto va bene finché non succede qualcosa di inatteso: si sgonfia una gomma, finisce la benzina, il motore si surriscalda. Se non «gestite» questa situazione (per esempio, non montate la ruota di scorta o non fate rifornimento), l’auto si ferma e non prosegue. Allo stesso modo, in un programma: se non si gestisce un’eccezione, l’applicazione termina in modo anomalo.
Eccezione (exception) — è un oggetto che viene creato nel momento in cui si verifica un problema durante l’esecuzione del programma. L’eccezione segnala: «Stop! Qualcosa è andato storto!»
Esempi di situazioni in cui si verificano eccezioni:
- Divisione per zero (10 / 0)
- Tentativo di accedere a un elemento dell’array che non esiste (arr[999])
- Apertura di un file che non è presente sul disco
- Conversione della stringa "abc" in un numero (Integer.parseInt("abc"))
Importante: le eccezioni non sono errori di compilazione (ad esempio, refusi nel codice), ma problemi che sorgono durante l’esecuzione del programma.
Perché le eccezioni sono utili?
- Codice pulito: la logica principale del programma non si appesantisce con controlli continui per ogni dettaglio.
- Flessibilità: è possibile gestire gli errori in modo centralizzato (ad esempio, tutti gli errori di lettura dei file in un unico punto).
- Affidabilità: il programma non «va in crash» con un messaggio criptico, ma indica che cosa è successo.
2. Eccezioni (Exceptions) vs Errori (Errors)
In Java esistono due tipi principali di problemi che possono verificarsi durante l’esecuzione di un programma:
Errori (Errors)
Gli errori sono problemi fatali e non recuperabili che derivano da malfunzionamenti della Java Virtual Machine (JVM) stessa. Di solito sono legati alle risorse del computer o a guasti interni della JVM.
Esempi di errori:
- OutOfMemoryError — memoria esaurita.
- StackOverflowError — overflow dello stack (ad esempio, per ricorsione infinita).
Importante: in genere non ha senso tentare di gestire questi errori nel programma.
Eccezioni (Exceptions)
Le eccezioni sono problemi con cui il programma può (e deve) convivere e che può gestire. Si verificano per errori nella logica del programma o per fattori esterni (ad esempio, l’utente ha inserito qualcosa di inatteso).
Esempi di eccezioni:
- NullPointerException — tentativo di usare null come se fosse un oggetto.
- ArrayIndexOutOfBoundsException — indice fuori dai limiti dell’array.
- IOException — errore nelle operazioni sui file.
In Java le eccezioni sono di due tipi:
- Checked exceptions (controllate) — il compilatore richiede che vengano gestite (per esempio, IOException).
- Unchecked exceptions (non controllate) — il compilatore non richiede che vengano gestite (per esempio, NullPointerException).
Schema: come sono organizzate
graph TD
Throwable --> Error
Throwable --> Exception
Exception --> RuntimeException
Exception --> Checked["(altre eccezioni)"]
style Throwable fill:#ffa64d,color:#000
style Exception fill:#ffa64d,color:#000
style Checked fill:#ffa64d,color:#000
style Error fill:#ff4d4d,color:#fff
style RuntimeException fill:#4dff88,color:#000
Spiegazione:
- Throwable — la radice dell’intera gerarchia di errori ed eccezioni in Java.
- Error — errori fatali della JVM, non vengono gestiti.
- Exception — eccezioni «normali» che si possono e si devono gestire.
- RuntimeException — eccezioni non controllate (errori del programmatore).
3. Come appare nel codice?
Esempio 1: divisione per zero
public class ExceptionDemo
{
public static void main(String[] args)
{
int a = 10;
int b = 0;
int c = a / b; // Qui si verificherà un'ArithmeticException!
System.out.println("Risultato: " + c);
}
}
Che cosa succederà?
Il programma terminerà con un errore e vedrete il messaggio:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionDemo.main(ExceptionDemo.java:5)
Esempio 2: accesso a un elemento inesistente dell’array
int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException
Esempio 3: lavoro con i file
import java.io.FileReader;
import java.io.IOException;
public class FileDemo
{
public static void main(String[] args) throws IOException
{
FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
int data = reader.read();
System.out.println(data);
reader.close();
}
}
Ora vediamo come gestire in modo elegante queste situazioni eccezionali.
GO TO FULL VERSION