2010-02-22 14 views
40

Dato questo codice:Ritorni multipli: quale imposta il valore di ritorno finale?

String test() { 
    try { 
     return "1"; 
    } finally { 
     return "2"; 
    } 
} 

fare le specifiche del linguaggio definiscono il valore di ritorno di una chiamata a test()? In altre parole: è sempre lo stesso in ogni JVM?

Nella JVM Sun il valore restituito è 2, ma voglio essere sicuro, che questo non dipenda dalla VM.

risposta

41

Sì, lo language spec definisce che "2" è il risultato. Se una VM lo fa in modo diverso, non è conforme alle specifiche.

Molti compilatori si lamenteranno a riguardo. Ad esempio, Eclipse dichiarerà che il blocco di reso non verrà mai eseguito, ma è sbagliato.

E 'incredibilmente cattiva pratica di scrivere codice come questo, non bisogna mai farlo :)

+2

Mi trattenni dal il minuto ho pensato, ma ancora ero curioso :) –

13

Il blocco finally viene sempre eseguito, tranne nel seguente esempio:

String test() { 
    try { 
     System.exit(0); 
    } finally { 
     return "2"; 
    } 
} 

In questo caso, la JVM si fermerà, senza eseguire il blocco finally.

Quindi nel vostro esempio, il valore restituito sarà 2.

+0

piace questa risposta – john

7

Sì, se si restituisce qualcosa dal blocco finally, sostituirà tutto ciò che è stato restituito dal blocco try o catch.

Lo stesso vale anche per le eccezioni . Se si butta qualcosa nel blocco finally, tale eccezione sostituirà qualsiasi eccezione sia stata generata nel blocco try o catch. Quindi fai attenzione a non gettare mai qualcosa nel blocco finally, perché potrebbe nascondere il motivo originale per un errore.

+1

un'altra cosa interessante è che se qualcosa è tornato da finalmente usando 'return' allora qualsiasi eccezione generata viene scartato. – sttaq

18

Sì, il linguaggio Java Specification è molto chiaro su questo tema (14.20.2):

Un'istruzione try con un blocco finally viene eseguito dal primo l'esecuzione del blocco try. Poi v'è una scelta:

  • Se l'esecuzione del blocco try viene completato normalmente, [...]
  • Se l'esecuzione del blocco try completa bruscamente a causa di un lancio di un valore V, [.. .]
  • Se l'esecuzione del blocco try viene completata improvvisamente per qualsiasi altra ragione R, viene eseguito il blocco finally. Poi v'è una scelta:
    • Se il blocco finally completa normalmente, [...]
    • Se il blocco finally completa bruscamente per la ragione S, allora l'istruzione try completa bruscamente per motivi S (e la ragione R è scartato).
0

è possibile consultare il link qui sotto. Spero che fornirà tutti i dettagli:

http://www.programmerinterview.com/index.php/java-questions/will-finally-run-after-return/

Dice blocco finally sarà sempre eseguito anche provare o blocco catch ha istruzione return. E se infine il blocco ha anche un'istruzione return, questo sovrascriverà l'istruzione return che è all'interno del blocco try o catch e in questo caso qualsiasi eccezione generata in try/catch verrà scartata (approccio errato).

Grazie, Chethan

2

Dopo aver letto il bytecode del programma, il codice è il seguente:

Il blocco finally dichiarazioni è inline prima della dichiarazione di ritorno del blocco try, in modo che il ritorno dalla fine il blocco viene eseguito per primo e l'istruzione di ritorno originale non lo fa mai.

Per Programma:

String test() { 
     try { 
      System.out.println("try"); 
      return "1"; 
     } finally { 
      System.out.println("finally"); 
      return "2"; 
     } 
    } 

Converte a:

String test() 
    { 
     System.out.println("try"); 
     String s = "1"; //temporary variable 
     System.out.println("finally"); 
     return "2"; 
     Exception exception; 
     exception; 
     System.out.println("finally"); 
     return "2"; 
    } 

E Per il programma: con blocco catch:

String test() { 

     try { 
      System.out.println("try"); 
      return "1"; 
     } catch (RuntimeException e) { 
      System.out.println("catch"); 
      return "2"; 
     } finally { 
      System.out.println("finally"); 
      return "3"; 
     } 
    } 

Converte a:

0.123.
String test() 
    { 
     System.out.println("try"); 
     String s = "1"; 
     System.out.println("finally"); 
     return "3"; 
     RuntimeException e; 
     e; 
     System.out.println("catch"); 
     String s1 = "2"; 
     System.out.println("finally"); 
     return "3"; 
     Exception exception; 
     exception; 
     System.out.println("finally"); 
     return "3"; 
    } 

Nota: conforme con JDK 1.7 & Decompilato utilizzando Cavaj.

+1

'throw e' non sarà mai raggiungibile. – Viks

+0

grazie a @Viks, ho aggiunto ulteriori approfondimenti dopo alcune ricerche. –