2697 Stimmen

Wird ein finally-Block in Java immer ausgeführt?

Bei diesem Code kann ich sicher sein, dass der finally-Block immer ausgeführt wird, egal was something() ist?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("Ich weiß nicht, ob das ausgegeben wird");
}

672 Stimmen

Wenn dies nicht der Fall ist, sollte das Schlüsselwort wie folgt lauten probably stattdessen.

61 Stimmen

3 Stimmen

Effektives Java sagt etwas anderes informit.com/articles/article.aspx?p=1216151&seqNum=7

135voto

WoodenKitty Punkte 6251

Hier ist eine Ausarbeitung von Kevin's Antwort. Es ist wichtig zu wissen, dass der Ausdruck, der zurückgegeben werden soll, vor finally ausgewertet wird, auch wenn er danach zurückgegeben wird.

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 übertrifft return... irgendwie");
        return 42;
    }
}

Ausgabe:

X
finally übertrifft return... irgendwie
42

10 Stimmen

Wichtig zu wissen.

0 Stimmen

Das ist gut zu wissen und macht auch Sinn. Es scheint, dass die tatsächliche Rückgabe des Wertes der Rückgabe ist, was nach kommt finally . Berechnung des Rückgabewerts ( printX() hier) kommt noch vor ihm.

2 Stimmen

Nö. Der obige Code sollte Folgendes ersetzen System.out.println("finally trumps return... sort of"); con System.out.print("finally trumps return in try"); return 42;

130voto

vibhash Punkte 1279

Ich habe das obige Beispiel mit geringfügigen Änderungen ausprobiert-

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.");
    }
}

Der obige Code gibt aus:

finally trumps return.
2

Dies liegt daran, dass bei Ausführung von return i; der Wert von i 2 beträgt. Danach wird der finally-Block ausgeführt, in dem 12 an i zugewiesen wird und dann System.out ausgeführt wird.

Nach Ausführung des finally-Blocks gibt der try-Block 2 zurück, anstatt 12 zurückzugeben, da diese return-Anweisung nicht erneut ausgeführt wird.

Wenn Sie diesen Code in Eclipse debuggen, wird der Eindruck entstehen, dass nach Ausführung von System.out des finally-Blocks die return-Anweisung des try-Blocks erneut ausgeführt wird. Dies ist jedoch nicht der Fall. Es gibt einfach den Wert 2 zurück.

12 Stimmen

Dieses Beispiel ist großartig, es fügt etwas hinzu, das in Dutzenden von verwandten Threads noch nicht erwähnt wurde. Ich denke, kaum ein Entwickler wird dies wissen.

5 Stimmen

Was wäre, wenn i kein primitives, sondern ein Integer-Objekt war.

0 Stimmen

Es fällt mir schwer, diesen Fall zu verstehen. docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.17 heißt es: "Eine Return-Anweisung mit einem Ausdruck versucht, die Kontrolle an den Aufrufer der Methode oder des Lambda-Körpers zu übergeben, die/der sie enthält.... Wenn die Auswertung des Ausdrucks normal abgeschlossen wird und einen Wert V. ergibt." Was ich aus dieser Aussage vermuten könnte, ist - es scheint, dass return den Ausdruck nicht noch einmal auswertet, sobald es den Wert V ausgewertet hat, deshalb wirkt sich ein geändertes i nicht auf den zurückgegebenen Wert aus, korrigiere mich.

53voto

Chris Cooper Punkte 16716

Das ist die ganze Idee eines finally-Blocks. Es ermöglicht Ihnen sicherzustellen, dass Sie Aufräumarbeiten durchführen, die andernfalls übersprungen werden könnten, weil Sie zurückkehren, unter anderem natürlich.

Finally wird aufgerufen, unabhängig von dem, was im try-Block passiert (es sei denn, Sie rufen System.exit(int) auf oder die Java Virtual Machine aus anderen Gründen beendet wird).

0 Stimmen

Das ist eine äußerst schwache Antwort. stackoverflow.com/a/65049/715269

42voto

Garth Gilmour Punkte 10840

Eine logische Möglichkeit, darüber nachzudenken, ist:

  1. Code, der in einem finally-Block platziert wird, muss egal was passiert innerhalb des try-Blocks ausgeführt werden
  2. Wenn also der Code im try-Block versucht, einen Wert zurückzugeben oder eine Ausnahme zu werfen, wird das Element 'auf das Regal gestellt', bis der finally-Block ausgeführt werden kann
  3. Weil der Code im finally-Block (per Definition) eine hohe Priorität hat, kann er zurückgeben oder werfen, was immer er will. In diesem Fall wird alles, was noch auf dem 'Regal' liegt, verworfen.
  4. Die einzige Ausnahme hiervon ist, wenn der VM während des try-Blocks vollständig herunterfährt, z.B. durch 'System.exit'

10 Stimmen

Ist dies nur "eine logische Art, darüber nachzudenken", oder ist dies wirklich die Art und Weise, wie der Final Block laut den Spezifikationen funktionieren soll? Ein Link zu einer Sun-Ressource wäre hier sehr interessant.

22voto

shyam Punkte 8656

finally wird immer ausgeführt, es sei denn, es liegt eine abnormale Programmbeendigung vor (wie das Aufrufen von System.exit(0)). Daher wird dein System.out gedruckt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X