Esegue finalmente un blocco anche se si lancia una nuova eccezione?


142

In questo codice verrà someVarimpostato anche se viene eseguito il blocco catch e viene generata la seconda eccezione?

public void someFunction() throws Exception {
    try {
        //CODE HERE
    } catch (Exception e) {
        Log.e(TAG, "", e);
        throw new Exception(e);
    } finally {
        this.someVar= true;
    }
}

2
Perché ci sono circostanze in cui il comportamento non è come previsto, come indicato da @GaryF
jax

1
Vale la pena notare che il blocco finale potrebbe non essere eseguito come previsto se genera un'eccezione o restituisce.
Peter Lawrey,

Risposte:


184

Sì, i blocchi finally funzionano sempre ... tranne quando:

  • Il thread che esegue il blocco try-catch-finally viene ucciso o interrotto
  • Usate System.exit(0);
  • La VM sottostante viene distrutta in qualche altro modo
  • L'hardware sottostante è in qualche modo inutilizzabile

Inoltre, se un metodo nel tuo blocco finalmente genera un'eccezione non rilevata, allora nulla verrà eseguito successivamente (ovvero l'eccezione verrà generata come in qualsiasi altro codice). Un caso molto comune in cui ciò accade è java.sql.Connection.close().

Per inciso, immagino che l'esempio di codice che hai usato sia solo un esempio, ma fai attenzione a mettere la logica effettiva all'interno di un blocco finally. Il blocco finally è destinato alla pulizia delle risorse (chiusura delle connessioni DB, rilascio di handle di file, ecc.), Non alla logica da eseguire. Se deve essere eseguito, fallo prima del blocco try-catch, lontano da qualcosa che potrebbe generare un'eccezione, poiché la tua intenzione è quasi certamente funzionalmente la stessa.


4
Cosa intendi qui con "Il thread che esegue il blocco try-catch-finally è [...] interrotto"? Forse quella documentazione è formulata in modo scadente, ma Thread.interrupt () non farà saltare il blocco finally, sia che venga lanciato dal blocco try o catch. Questo usa "interrotto" per significare qualcosa di più violento, come Thread.stop ()?
Joe Kearney,

@Joe: Sì, penso che la documentazione sia un po 'mal formulata qui, e che significhino un'interruzione generale dell'attività del thread.
GaryF,

@GaryF - Penso che stai citando dal JLS. La formulazione di JLS è talvolta un po 'strana, ma in genere scoprirai che il significato della strana terminologia è definito chiaramente altrove nel documento. JLS è una specifica e ha come obiettivo primario la precisione (anziché la leggibilità).
Stephen C,

1
@Stephen C - In realtà, proveniva dal tutorial JavaSE (collegato da altri). Potrebbe essere formulato in modo simile nel JLS, ma non riesco a trovare la parte rilevante. Me lo sarei aspettato nel capitolo 11 (Eccezioni), nel capitolo 14 (Dichiarazioni) o nel capitolo 15 (Espressioni), ma non vedo nulla che si riferisca esplicitamente alle interruzioni. Sarei sicuramente interessato a vederlo.
GaryF,

1
@GaryF - Capisco. In realtà il JLS parla della terminazione "normale" e "brusca" delle dichiarazioni, e c'è una sezione (14.1) che definisce la terminologia. Il comportamento di finallyviene quindi specificato in termini di terminazioni normali e improvvise.
Stephen C,

10

Sì.

Vedi la documentazione :

Il blocco finally viene sempre eseguito alla chiusura del blocco try.

eccezioni:

Nota: se la JVM viene chiusa durante l'esecuzione del codice try o catch, il blocco finally potrebbe non essere eseguito. Allo stesso modo, se il thread che esegue il codice try o catch viene interrotto o ucciso, il blocco finally potrebbe non essere eseguito anche se l'applicazione nel suo insieme continua.


2

Infine, il blocco viene sempre eseguito.

public class ExceptionTest {

public static void someFunction(String input) throws Exception {
    try {
        if( input.equals("ABC") ) {
            System.out.println("Matched");
        }
    } catch (Exception e) {
        throw new Exception(e);
    } finally {
        System.out.println("Input Is "+input+" Finally Executed!!!");
    }
}

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
        System.out.println("********* Test with VALUE ********* ");
        someFunction("ABC");
        System.out.println("\r\n********* Test with NULL  ********* ");
        someFunction(null);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

Java Try Catch Finalmente Blocca con Throw


2

Alla fine viene sempre eseguito, indipendentemente dal tuo caso

  • blocco try-catch-finally
  • getta

Per eccezioni non controllate, java non richiede, gestione degli errori. questo è il motivo, se si verifica un'eccezione non selezionata nel blocco infine, quindi non viene eseguita alcuna gestione, il codice scritto sotto questo punto (dove si è verificato l'errore) non verrà eseguito.

Quindi suggerisco di gestire sempre tutte le eccezioni che possono essere selezionate o deselezionate. In questo modo puoi assicurarti che anche il blocco di codice sia finalmente eseguito, indipendentemente dal fatto che si verifichi anche un'eccezione non selezionata. hai un posto nella cattura del sotto-nido e infine blocca per completare il lavoro necessario.



1

Sì. finallyIl blocco viene eseguito sempre tranne il caso in cui si chiama System.exit () perché arresta la VM Java.


Gli hook di arresto vengono comunque chiamati dopo System.exit (), ma i thread non di sistema esistenti vengono tutti arrestati.
Peter Lawrey,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.