2013-03-05 15 views
44

Durch das Lesen aller Fragen bereits in diesem Forum im Zusammenhang mit dem oben genannten Thema (siehe Titel) gestellt, verstehe ich sehr gut, dass finally immer aufgerufen wird. (außer von System.exit und Endlosschleifen). Ich würde jedoch gerne wissen, ob ein return in einem catch-Block aufgerufen wird und dann ein weiterer return vom finally-Block aufgerufen wird.Try-catch-finally-return Klärung

Zum Beispiel:

public static void main(String[]args) { 
    int a = new TestClass().absorbeTheValue(); 
} 

int absorbeTheValue() { 
    try { 
     int a = 10/0; 
     if (a > 0) return 4; 
    } catch(Exception e) { 
     return 45; 
    } finally { 
     return 34; 
    } 
}  

Also hier der Ausgang (wenn die Methode aufgerufen wird) wird 34 in jedem Fall sein. Es bedeutet, dass schließlich immer ausgeführt wird. Ich denke aber, dass die anderen "Returns" überhaupt nicht laufen. In vielen Beiträgen fand ich die Tatsache, dass endlich der Inhalt über das geschrieben wurde, was schon durch die Rückgabeklausel geschrieben wurde. Mein Verständnis ist, dass, sobald der Rückgabewert in der catch-Klausel evaluiert wird, der Kontrollfluss an die finally-Klausel übergeben wird, die wiederum eine weitere Rückgabe hat, diesmal wird die Rückgabe ausgewertet, ohne die Kontrolle an die catch-Klausel zurückzugeben . Auf diese Weise wird die einzige zur Laufzeit aufgerufene return die endgültige Rückkehr sein. Sind Sie einverstanden (damit?

Ein return in finally gibt das Steuerelement nicht an das Programm zurück, aber gibt den Wert zurück und beendet die Methode. Können wir das sagen?

+4

einrücken Code bitte. –

+0

Siehe auch: http://stackoverflow.com/questions/65035/in-java-does-return-trump-finally –

+0

Was ist Ihre Frage? – thiagoh

Antwort

77

Wenn der return Block try erreicht ist, überträgt er die Kontrolle an den finally Block, und die Funktion kehrt schließlich normal zurück (kein Wurf).

Wenn eine Ausnahme auftritt, aber dann erreicht der Code ein return vom catch Block, die Steuerung an den finally Block übertragen wird, und die Funktion kehrt schließlich normal (kein Wurf).

In Ihrem Beispiel haben Sie eine return im finally, und so unabhängig davon, was passiert, wird die Funktion 34 zurückkehren, weil finally das Finale hat (wenn man so will) Wort.

Obwohl es nicht in Ihrem Beispiel bedeckt, wäre dies wahr sein, auch wenn Sie nicht die catch haben und wenn eine Ausnahme in dem try Block geworfen wurde und nicht gefangen. Indem Sie einen return aus dem finally-Block ausführen, unterdrücken Sie die Ausnahme vollständig. Bedenken Sie:

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

    private static int foo(String[] args) { 
    try { 
     int n = Integer.parseInt(args[0]); 
     return n; 
    } 
    finally { 
     return 42; 
    } 
    } 
} 

Wenn Sie ausführen, ohne irgendwelche Argumente zu liefern:

$ java FinallyReturn

... der Code in foo eine ArrayIndexOutOfBoundsException wirft. Aber weil der finally Block eine return macht, wird diese Ausnahme unterdrückt.

Dies ist ein Grund, warum es am besten ist, return in finally zu vermeiden.

+0

Es ist wichtig zu beachten, dass 'throw' für diese Zwecke mit' return' austauschbar ist. (Z. B., werfen neue Ausnahme (4) ',' werfen neue Ausnahme (34) ') – Marcus

+0

Ich möchte nur auf, was user1442960 gesagt chip. Die JLS sagt nichts über eine Rückkehr in einem Fang oder schließlich. Es verwendet den Begriff "abrupt", was, wie ich vermute, entweder eine Ausnahme oder eine Rückkehr bedeutet. – Steve11235

+1

@ Steve11235: Nein, ein "Return" von einem "Catch" Block würde "normal", nicht "abrupt" abgeschlossen werden. Dies ergibt sich aus [Abschnitt 11] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-11.html): * "Während des Auslösens einer Ausnahme wurde Java Virtual Die Maschine beendet abrupt alle Ausdrücke, Anweisungen, Methoden- und Konstruktoraufrufe, Initialisierer und Feldinitialisierungsausdrücke, die im aktuellen Thread begonnen, aber nicht vollständig ausgeführt wurden. "* –

53

Hier ist ein Code, der zeigt, wie es funktioniert.

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

    public static String test() 
    { 
     try { 
      System.out.println("try"); 
      throw new Exception(); 
     } catch(Exception e) { 
      System.out.println("catch"); 
      return "return"; 
     } finally { 
      System.out.println("finally"); 
      return "return in finally"; 
     } 
    } 
} 

Die Ergebnisse sind:

try 
catch 
finally 
return in finally 
+3

+1 leicht zu verstehen und brachte mir etwas Neues bei:) – Logan

+1

@LoganDam TJ Crowder gibt eine sehr gute Erklärung. – andre

+0

@LoganDam: Es ist eine nette, saubere Erklärung der Reihenfolge der Operationen. Es beantwortet jedoch nicht die gestellte Frage. Die Frage fragt explizit, was passiert, wenn ein 'finally'-Block eine' return'-Anweisung enthält. – unholysampler