vuoi
o PayPal
tutte le volte che vuoi
Quando si verifica un errore, il metodo che lo ha generato non
· sempre ha la possibilità di porre rimedio ad esso, ma potrà
delegare il chiamante a gestire direttamente l’eccezione o a
rilanciarla a sua volta. La gestione può essere delegata a uno dei
metodi la cui cascata di chiamate invoca il metodo che lancia
l’eccezione. La gestione delle eccezioni consente di trasferire il
controllo dell’errore (rilanciare) dal punto in cui si manifesta al
punto del programma in cui è possibile gestire (catturare)
l’errore, ripristinando la situazione corretta.
Un buon programma Java dovrebbe rispettare il Catch or Specify
· Requirement, ossia il codice che può generare una eccezione
dovrebbe:
Catturarla e gestirla (try-catch)
· Essere racchiuso in un metodo che la rilancia (throws)
· quindi si va a risolvere l’eccezione da un’altra parte del
programma
Throws potrebbe essere utile per la riusabilità del codice
Se l’eccezione non viene gestita da qualche parte, allora varrà
propagata fino al main dove verrà interrotto producendo un
messaggio di errore, il messaggio include il tipo di eccezione
lanciata e la pila delle chiamate ai metodi che consentono di
individuare il
punto del programma in cui l’eccezione si è verificata.
2 tipi di eccezioni:
· Checked: sono quelle per cui è già previsto che un certo
· codice potrà generare un'eccezione
I metodi che le possono generare sono obbligati a stabilire
una politica per gestirle (o propagando l’eccezione indietro
nello stack di chiamate, o gestendola in qualche modo). Un
metodo che non gestisce localmente un’eccezione
controllata è obbligato a dichiarare che può sollevare quel
tipo di eccezione, mediante la keyword throws, così
l’eccezione viene propagata a chi chiamerà quel metodo,
che dovrà trovare un modo per rioslverla
Esempio: apertura di file inesistente
Runtime: sono non note e vengono scoperte in fase di
· esecuzione e sta alla sensibilità dello sviluppatore
prevederle
I metodi non sono obbligati a stabilire una politica per le
eccezioni non controllate lanciate dalla loro
implementazione (e spesso non le gestiscono).
Le eccezioni a runtime non siamo obbligati a gestirle, le altre si,
ad esempio nel caso della IOException è sicuro che ci potrebbe
essere un problema ad esempio se provo ad aprire un file aperto
con un altro programma di scrittura, quel file non può essere
editato
Esempi di eccezioni:
· ArithmeticException
· errori in operazioni aritmetiche, es. divisione per zero
IllegalArgumentException
· Quando il chiamante passa un argomento inappropriato
NumberFormatException
· quando si tenta di convertire una stringa in un formato
numerico e la stringa non ha un valore appropriato
ArrayIndexOutOfBoundsException
· quando si utilizza un indice esterno al range valido per un
array
ClassCastException
· Si verifica quando proviamo a fare male il cast di qualcosa
StringIndexOutOfBoundsException
· quando si tenta di accedere ad una posizione inesistente di
una stringa
NegativeArraySizeException
· quando si tenta di creare un array di dimensione negativa
NullPointerException
· quando si tenta di accedere ad un oggetto tramite
riferimento null
Si può lanciare un’eccezione, ad esempio:
· static int calc(int num1, int num2, int div) {
if(div == 0)
throw new IllegalArgumentException("Divisore non valido");
int val = (num1 + num2)/div;
return val;
}
Con l'operatore new alloco l'oggetto che rappresenta l'eccezione
e con l'operatore throw lo lanciamo. Potrei anche non mettere
throw, con il throw trasformo la mia eccezione in un'eccezione
controllata perchè sono io sviluppatore che la sto controllando
dichiarandolo ufficialmente.
Il blocco try-catch è un blocco di gestione delle eccezioni. Con
· questo costrutto possiamo provare a risolvere le eccezioni.
Mediante il try-catch è come se stessimo dicendo che c'è un
percorso principale, se però si verifica un problema allora cattura
un problema e fai qualcosa, è sostanzialmente un percorso
alternativo nel caso in cui ci sia un problema. Il blocco try-catch
si legge come "prova a eseguire le istruzioni presenti nel blocco
try, se c'è un'eccezione ti dico io come risolvere, te lo dico nel
catch" la soluzione presente nel catch è detta in maniera custom,
cioè il catch ha bisogno di sapere un template cioè quale
eccezione devo sistemare, posso essere generico e dirgli di
lavorare su qualsiasi eccezione. Possiamo aggiungere quanti
catch vogliamo e l'ordine di esecuzione è l'ordine di
dichiarazione.
Bisogna fare attenzione a ciò che mettiamo nel try, se infatti
mettiamo qualcosa che va a manipolare dati del programma
stesso e si genera un’eccezione, tutto ciò che abbiamo scritto nel
try e che è stato eseguito decade, se invece nel try c’è qualcosa
di “esterno”, quindi ad esempio di fa una chiamata a un sito web,
ciò che è stato fatto ormai è stato fatto
Le eccezioni si propagano finché si incontra un metodo che
· intercetta e gestisce l’eccezione, oppure finché non termina
anche il metodo main. Per intercettare e gestire un’eccezione ad
un livello più esterno, il metodo che produce l’eccezione deve
essere invocato all’interno di un blocco try che possieda la
clausola catch appropriata per gestirla.
Try-catch può essere usato anche nel caso dei cast, infatti invece
· di scrivere qualcosa del tipo if (p instanceof studente), che è
sbagliato perché mi intrometto tra l’interazione dello studente e
del metodo in cui si trova l’if, posso fare un try-catch, nel try
metto un cast del tipo s=(studente)p;
Clausola finally: essa può essere associata al try, indica una
· parte del codice che deve essere eseguita a prescindere da cosa
sia accaduto nel try
La finally si usa poco, può essere utile solo se abbiamo una
qualche istruzione che vogliamo sia eseguita sia se si segue il try
che si segue uno qualunque del catch
Il finally si mette dopo il catch del tipo: