L'esecuzione di alcune cose può potenzialmente portare dei problemi. Questi problemi sono detti "eccezioni".
Un metodo che esegue delle istruzioni "potenzialmente pericolose" può decidere di fare 3 cose:
1) Gestire completamente queste situazioni
2) Fregarsene altamente e delegare al suo chiamante l'onere di gestirle
3) Gestire alcune situazioni e delegare l'onere al chiamante di gestirne altre
Il costrutto try/catch serve a gestire una o più eccezioni:
try {
... // Istruzioni "pericolose"
} catch (Eccezione1 e1) {
... // Gestisco la problematica numero 1
} catch (Eccezione2 e2) {
... // Gestisco la problematica numero 2
}
Se tutte le situazioni pericolose sono gestite tramite l'apposita sezione catch(), il metodo è "sicuro": non può accadere nulla che lui non sia in grado di gestire.
Se, al contrario, il metodo non vuole (o non può) gestire le eccezioni, allora dichiara di poterne sollevare e sarà compito di chi lo chiama gestirle (o passarle a sua volta). In questo caso, il metodo farà uso della clausola throws.
Può esserci il caso in cui il metodo sia in grado di gestire alcune eccezioni, ma non altre che possono sollevarsi (o, addirittura, può egli stesso sollevarne in caso vi siano problemi sui dati). In questo caso, il metodo dovrà dichiarare le eccezioni che non intende (o non può) gestire, mentre dovrà gestore con try/catch il resto.
L'istruzione throw serve a sollevare un'eccezione. Se, ad esempio, un metodo deve lavorare con determinati dati, ma questi dati sono errati, può di sua iniziativa sollevare un'eccezione (che va dichiarata!) usando appunto l'istruzione throw.
La regola fondamentale, comunque, rimane sempre la stessa. Quando ci sono di mezzo istruzioni pericolose, quindi ci sono in ballo le eccezioni, il metodo che esegue le istruzioni pericolose deve decidere una delle seguenti due cose:
1) Gestire le eccezioni (try/catch)
oppure
2) Delegare al chiamante (throws)
Ciao.