Le eccezioni sono classi che ereditano Exception
, sono utilizzate per segnalare una condizione anomale che impediscono la normale prosecuzione del programma.
Tipi di Errori
Ci sono due tipologie di errori: Sincroni si verificano dopo l’esecuzione di un’istruzione e possono essere gestiti tramite un eccezione, si dividono in:
- Errori non critici: Condizioni anomale del nostro codice (divisione 0)
- Critici o irrecuperabili: Errori interni alla JVM (conversioni non consentita mancanza di memoria)
Asincroni avvengono parallelamente all’esecuzione del programma e sono indipendenti dal flusso di controllo, non possono essere gestiti via software (completamenti nel trasferimento I/O)
Gestione delle Eccezioni
Politica del Catch or Declare: indica che un metodo che può avere degli errori deve decidere se gestire l’eccezione utilizzando il blocco try-catch
oppure se ignorarla utilizzando throws
.
Throws: Se si decide di ignorare l’eccezione il metodo deve indicare il tipo di eccezione che può sollevare attraverso throws
. Se tutti i metodi all’interno dell’albero delle chiamate dell’esecuzione decidono di ignorare l’eccezione, l’esecuzione viene interrotta, stampando la stack trace.
Try-Catch: Le eccezioni possono essere gestite attraverso il blocco try-catch
dove:
- nel blocco
try
vengono inserite le istruzioni che potrebbero ritornare un eccezione che vogliamo catturare - nel intestazione del blocco
catch
definiamo il tipo di eccezione da gestire, all’interno del blocco si specifica l’azione da attuare a seguito dell’eccezione sollevata.
È possibile definire più blocchi catch
per tipi di exception diverse me è importante dichiarali nel ordine giusto ovvero dalla catch più specifico al meno specifico. Infatti la JVM utilizza il primo catch compatible anche se non è il più specifico.
Dopo il costrutto try-catch
è possibile inserire un blocco finaly
che contiene del codice che verrà sempre eseguito dopo il blocco try
, ad esempio la chiusura di un file.
Stack Trace
La stack trace è il messaggio a schermo che descrive l’errore, contenendo:
- thread sul quale è stata sollevata l’eccezione
- nome dell’eccezione
- la successione in ordine inverso inverso delle invocazione dei metodi coinvolti.
- file sorgente e il numero di riga di ogni invocazione
Gerarchia delle Classi di Errore
Come radice della gerarchia abbiamo la classe Throwable
che estende direttamente la classe Object
.
Come dirette sottoclassi di Throwable
troviamo la classe Error
e la classe Exception
:
Le Exception possono essere divide in due categorie
- RuntimeException: ovvero eccezioni interne JVM legate ad errori nella logica del programma (es.
nullPointerException
) - Eccezioni regolari: errori che le applicazioni dovrebbero anticipare e dalle quali poter riprendersi (es.
IOException
)
Gli Error riguardano condizioni di eccezione irrecuperabili, sono rari e non dovrebbero essere considerati dalle applicazioni
checked e unchecked
Eccezioni di tipo checked:
- È sempre necessario attenersi al paradigma catch-or-declare
- Sono eccezioni comuni, ovvero quelle che estendono Exception (ma non RuntimeException)
- Esempi:
ParseException
,ClassNotFoundException
,FileNotFoundException
Eccezioni di tipo unchecked:
- Non si è obbligati a dichiarare le eccezioni sollevate o a catturarle in un blocco try-catch (ma è possibile farlo)
- Sono eccezioni che estendono Error o RuntimeException
- Esempi:
IndexOutOfBoundsException
,ClassCastException
,NullPointerException
,ArithmeticException
,OutOfMemoryError
Eccezioni Personalizzate
Possiamo definire le nostre eccezioni personalizzate che poi verranno generate dai nostri metodi, se un metodo genera un’eccezione deve dichiararlo nel nell’intestazione.
class MiaEccezione extends Exception { ... }
class MiaClasse {
private Utente amministratore;
public void leggiInformazioni(Utente u) throws MiaEccezione {
if(!amministratore.equals(u)) throw new MiaEccezione();
}
}