Domanda Finalmente esegue sempre in Java?


Considerando questo codice, posso esserlo assolutamente sicuro che il finally il blocco si esegue sempre, non importa cosa something() è?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("i don't know if this will get printed out.");
}

1900
2017-09-15 17:43


origine


risposte:


Sì, finally sarà chiamato dopo l'esecuzione del try o cattura i blocchi di codice.

Le uniche volte finally non saranno chiamati sono:

  1. Se invochi System.exit();
  2. Se la JVM si arresta prima
  3. Se la JVM raggiunge un ciclo infinito (o qualche altra istruzione non interrompibile e non terminante) nel try o catch bloccare;
  4. Se il sistema operativo termina forzatamente il processo JVM; per esempio. "kill -9" su UNIX.
  5. Se il sistema host muore; per esempio. mancanza di corrente, errore hardware, panico del sistema operativo, eccetera.
  6. Se finalmente il blocco verrà eseguito dal thread daemon e tutti gli altri thread non daemon escono prima che venga finalmente chiamato.

2112
2017-09-15 17:45



Codice di esempio:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("finally trumps return.");
    }
}

Produzione:

finally trumps return. 
0

444
2017-09-15 17:59



Inoltre, anche se è una cattiva pratica, se c'è un'istruzione return nel blocco finally, vincerà qualsiasi altro return dal blocco regolare. Cioè, il seguente blocco restituirebbe falso:

try { return true; } finally { return false; }

Stessa cosa con il lancio di eccezioni dal blocco finale.


323
2017-09-15 18:19



Ecco le parole ufficiali della specifica del linguaggio Java.

14.20.2. Esecuzione di try-finally e try-catch-finally

UN try dichiarazione con a finally il blocco viene eseguito eseguendo prima il try bloccare. Quindi c'è una scelta:

  • Se l'esecuzione del try il blocco termina normalmente, [...]
  • Se l'esecuzione del try il blocco termina bruscamente a causa di a throw di un valore V, [...]
  • Se l'esecuzione del try il blocco termina bruscamente per qualsiasi altro motivo R, poi il finally il blocco viene eseguito. Quindi c'è una scelta:
    • Se il blocco finally termina normalmente, quindi il try la dichiarazione si conclude bruscamente per la ragione R.
    • Se la finally il blocco termina bruscamente per la ragione S, poi il try la dichiarazione si conclude bruscamente per la ragione S (e ragione R viene scartato).

Le specifiche per return rende esplicitamente questo:

JLS 14.17 Dichiarazione di reso

ReturnStatement:
     return Expression(opt) ;

UN return dichiarazione con no Expression  tentativi per trasferire il controllo al invoker del metodo o costruttore che lo contiene.

UN return dichiarazione con un Expression  tentativi per trasferire il controllo al invoker del metodo che lo contiene; il valore del Expression diventa il valore dell'invocazione del metodo.

Le descrizioni precedenti dicono "tentativi trasferire il controllo"piuttosto che solo"trasferisce il controllo"perché se ce ne sono try dichiarazioni all'interno del metodo o costruttore di cui try i blocchi contengono il return affermazione, poi qualsiasi finally clausole di quelli try le istruzioni saranno eseguite, nell'ordine, più a fondo, più esterne, prima che il controllo venga trasferito all'invocatore del metodo o costruttore. Completamento brusco di a finally la clausola può interrompere il trasferimento del controllo avviato da a return dichiarazione.


229
2018-05-25 06:50



Oltre alle altre risposte, è importante sottolineare che "finally" ha il diritto di ignorare qualsiasi eccezione / valore restituito dal blocco try..catch. Ad esempio, il codice seguente restituisce 12:

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

Allo stesso modo, il seguente metodo non genera un'eccezione:

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

Mentre il seguente metodo lo lancia:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}

134
2018-05-13 07:11



Ho provato l'esempio sopra con leggera modifica-

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

Il codice sopra riportato produce:

finalmente briscola ritorno.
  2

Questo perché quando return i; viene eseguito i ha un valore 2. Dopo questo il finally il blocco viene eseguito dove 12 è assegnato a i e poi System.out fuori viene eseguito.

Dopo aver eseguito il finally bloccare il try blocco restituisce 2, anziché restituire 12, perché questa dichiarazione di ritorno non viene eseguita nuovamente.

Se esegui il debug di questo codice in Eclipse, avrai la sensazione che dopo l'esecuzione System.out di finally bloccare il return dichiarazione di try il blocco viene eseguito di nuovo. Ma questo non è il caso. Restituisce semplicemente il valore 2.


87
2017-11-17 16:25



Ecco un'elaborazione di La risposta di Kevin. È importante sapere che l'espressione da restituire viene valutata in precedenza finally, anche se viene restituito dopo.

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
    }
}

Produzione:

X
finally trumps return... sort of
0

79
2017-12-03 23:36



Questa è l'idea di un blocco finale. Ti permette di assicurarti di eseguire delle pulizie che altrimenti potrebbero essere saltate perché tu ritorni, tra le altre cose, ovviamente.

Alla fine viene chiamato indipendentemente da cosa succede nel blocco try (salvo che chiami System.exit(int) o Java Virtual Machine prende il via per qualche altra ragione).


46
2018-05-13 06:19