La Clausola finally in Java
- La clausola
finally
in Java garantisce l'esecuzione di un blocco di codice dopo un bloccotry
/catch
, indipendentemente dalla presenza o meno di eccezioni. - È utile per garantire che determinate operazioni, come la chiusura di file o il rilascio di risorse, vengano sempre eseguite, anche in caso di errori.
- Il blocco
finally
è opzionale, ma ogni istruzionetry
richiede almeno un bloccocatch
o un bloccofinally
.
Clausola finally
Quando vengono generate delle eccezioni, l'esecuzione in un metodo assume un percorso piuttosto brusco e non lineare che altera il normale flusso del metodo.
A seconda di come è stato codificato il metodo, è persino possibile che un'eccezione causi l'uscita anticipata dal metodo. Questo può costituire un problema in alcuni metodi. Ad esempio, se un metodo apre un file all'ingresso e lo chiude all'uscita, allora non si vorrà che il codice che chiude il file venga bypassato dal meccanismo di gestione delle eccezioni.
La parola chiave finally
è stata progettata per affrontare questa eventualità.
finally
crea un blocco di codice che verrà eseguito dopo che un blocco try
/catch
è stato completato e prima del codice che segue il blocco try
/catch
.
Il blocco finally
verrà eseguito sia che venga generata un'eccezione, sia che non venga generata.
Se viene generata un'eccezione, il blocco finally
verrà eseguito anche se nessuna istruzione catch
corrisponde all'eccezione.
Ogni volta che un metodo sta per restituire il controllo al chiamante da dentro un blocco try
/catch
, tramite un'eccezione non catturata o un'istruzione return
esplicita, il blocco finally
viene anch'esso eseguito poco prima che il metodo ritorni. Questo può essere utile per chiudere file o liberare altre risorse che potrebbero essere state allocate all'inizio di un metodo con l'intento di essere smaltite prima del ritorno.
Il blocco finally
è opzionale. Tuttavia, ogni istruzione try
richiede almeno un blocco catch
o un blocco finally
.
Ecco un esempio di programma che mostra tre metodi che terminano in modi diversi, nessuno dei quali esce senza eseguire i rispettivi blocchi finally
:
// Dimostrare finally.
class DemoFinally {
// Generare un'eccezione fuori dal metodo.
static void metodoA() {
try {
System.out.println("dentro metodoA");
throw new RuntimeException("demo");
} finally {
System.out.println("finally di metodoA");
}
}
// Restituire da dentro un blocco try.
static void metodoB() {
try {
System.out.println("dentro metodoB");
return;
} finally {
System.out.println("finally di metodoB");
}
}
// Eseguire un blocco try normalmente.
static void metodoC() {
try {
System.out.println("dentro metodoC");
} finally {
System.out.println("finally di metodoC");
}
}
public static void main(String[] args) {
try {
metodoA();
} catch (Exception e) {
System.out.println("Eccezione catturata");
}
metodoB();
metodoC();
}
}
In questo esempio, metodoA()
esce prematuramente dal blocco try
generando un'eccezione. Il blocco finally
viene eseguito durante l'uscita. Il blocco try
di metodoB()
viene terminato tramite un'istruzione return
. Il blocco finally
viene eseguito prima che metodoB()
ritorni. In metodoC()
, l'istruzione try
viene eseguita normalmente, senza errori. Tuttavia, anche in questo caso il blocco finally
viene eseguito.
Esecuzione garantita di finally
Se un blocco finally
è associato a un try
, il blocco finally
verrà eseguito alla conclusione del try
in qualunque caso.
Ecco l'output generato dal programma precedente:
dentro metodoA
finally di metodoA
Eccezione catturata
dentro metodoB
finally di metodoB
dentro metodoC
finally di metodoC