Differenze tra le versioni di "Java/Gestione delle eccezioni"

Correggo tag deprecato
m (Bot: sostituzione tag obsoleti)
(Correggo tag deprecato)
 
== Un esempio ==
Si vuole implementare una calcolatrice. Si divide il programma in due parti: le classi che realizzano l'interfaccia grafica, e le classi del "motore" matematico che esegue i calcoli. A tempo di esecuzione, l'utente inserisce un'espressione matematica nell'interfaccia grafica, quest'ultima passa l'espressione al motore, che calcola e restituisce il risultato, e l'interfaccia grafica lo mostra all'utente. La UI accede al motore tramite i metodi di questa classe:
<sourcesyntaxhighlight lang="java">
public class MathServer {
/**
}
}
</syntaxhighlight>
</source>
 
Il metodo "promette" ai client che esso
#altrimenti, restituisce il risultato.
 
<sourcesyntaxhighlight lang="java">
public class MathServer {
/**
}
}
</syntaxhighlight>
</source>
 
Equivalentemente:
<sourcesyntaxhighlight lang="java">
public class MathServer {
/**
}
}
</syntaxhighlight>
</source>
 
In questo caso si è sostituita la clausola "si interrompe e segnala il problema al chiamante" con "lancia una eccezione", tuttavia esistono [[#Altre_tecniche|altre tecniche]].
; Prova
Eseguendo questo programma di prova...
<sourcesyntaxhighlight lang="Java">
 
public class TestDivisione {
}
 
</syntaxhighlight>
</source>
... si otterrà un risultato come questo, sulla console:
<sourcesyntaxhighlight lang="Java">
Il risultato di 10 diviso 0 è:
Exception in thread "main" java.lang.ArithmeticException: Divisione per zero
at MathServer.calcola(MathServer.java:24)
at TestDivisione.main(TestDivisione.java:7)
</syntaxhighlight>
</source>
 
Il significato dell'output è questo: il programma ha eseguito con successo il codice fino alla prima <code>System.out.println</code>, ma non è mai arrivato alla seconda, in quanto è incappato in una {{Java/Javadoc|java.lang.ArithmeticException|javadoc=java/lang/ArithmeticException.html}}, il cui messaggio è "Divisione per zero", che è stata lanciata dal metodo MathServer.calcola al metodo TestDivisione.main. È indicato anche il punto esatto in cui ciascun metodo ha ricevuto l'eccezione: MathServer l'ha lanciata all'istruzione presente nella riga 24 del file MathServer.java (non riportata nel codice sopra) e TestDivisione l'ha ricevuta all'istruzione presente nella riga 7 del file TestDivisione.java, ovvero
<sourcesyntaxhighlight lang="Java">
int risultato= MathServer.calcola("" + dividendo + " / " + divisore);
</syntaxhighlight>
</source>
 
Questo è esattamente il comportamento che ci si deve aspettare dal programma, in quanto la specifica del metodo MathServer.calcola() stabilisce chiaramente che deve essere così.
 
Eseguendo questo programma di prova...
<sourcesyntaxhighlight lang="Java">
public class TestDivisione {
 
 
}
</syntaxhighlight>
</source>
... si otterrà un risultato come questo, sulla console:
<sourcesyntaxhighlight lang="Java">
Il risultato di 10 diviso 0 è:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at TestDivisione.main(TestDivisione.java:7)
</syntaxhighlight>
</source>
 
Il significato dell'output è questo: il programma ha eseguito con successo il codice fino alla prima <code>System.out.println</code>, ma non è mai arrivato alla seconda, in quanto è incappato in una {{Java/Javadoc|java.lang.ArithmeticException|javadoc=java/lang/ArithmeticException.html}} il cui messaggio è "/ by zero", che è stata lanciata nel metodo TestDivisione.main(), in particolare nell'istruzione presente nella riga 7 del file TestDivisione.java, ovvero
<sourcesyntaxhighlight lang="Java">
int risultato= dividendo / divisore;
</syntaxhighlight>
</source>
 
In effetti, la [http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.6 specifica di linguaggio] stabilisce che l'operatore di divisione lancia una ArithmeticException se l'operando a destra (il divisore) è pari a zero.
&nbsp;&nbsp;&nbsp;&nbsp;<code>throw ''espressione'';</code><br/>
dove ''espressione'' è di tipo <code>java.lang.Throwable</code> o sottotipo. Tipicamente, anche se non è obbligatorio, l'eccezione viene creata appena prima di essere lanciata.
<sourcesyntaxhighlight lang="Java">
throw new ArithmeticException("Divisione per zero!");
</syntaxhighlight>
</source>
 
La JVM può lanciare eccezioni al verificarsi di determinati casi stabiliti dalla specifica, e sono lanciate in assenza di una istruzione <code>throw</code>.
== Handle... ==
Per gestire le eccezioni {{chiarire|si usa la seguente sintassi|aggiornare con ARM e multi-catch clause}}:
<sourcesyntaxhighlight lang="Java">
try {
// Codice che può lanciare eccezioni
// Codice da eseguire prima dell'uscita dal try-catch-finally
}
</syntaxhighlight>
</source>
 
Questa istruzione viene eseguita come di seguito:
 
I blocchi <code>catch</code> possono essere in numero arbitrario e contengono il codice che gestisce la situazione anomala corrispondente ad una certa eccezione. Ogni blocco catch è specifico di un determinato tipo di eccezione, che ovviamente deve essere una sottoclasse di Throwable. Quel blocco cattura tutte le eccezioni che sono istanze di quel tipo, a meno che non sia preceduto da un blocco catch più specifico, ad esempio:
<sourcesyntaxhighlight lang="Java">
catch(FileNotFoundException x) { ... }
catch(IOException x) { ... }
</syntaxhighlight>
</source>
In questo caso, il secondo blocco cattura tutte le IOException che '''non''' sono anche FileNotFoundException, in modo che ogni eccezione sia gestita una sola volta.
 
 
== ... or declare ==
<sourcesyntaxhighlight lang="Java">
/**
* @throws IllegalArgumentException Se <code>prova</code> è minore di zero.
...
}
</syntaxhighlight>
</source>
 
Un metodo dovrebbe sempre dichiarare tutte le eccezioni che si prevede esso potrà lanciare. Ciò si fa con la clausola <code>throws</code>. Essa contiene obbligatoriamente tutte le eccezioni ''checked'', e in più può contenere anche eccezioni ''unchecked''. In ogni caso, è bene documentare ciascuna eccezione riportando una descrizione nella documentazione del metodo.