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

3019voto

jodonnell Punkte 48623

Ja, finally wird nach der Ausführung der try oder catch Codeblöcke aufgerufen.

Die einzigen Zeiten, in denen finally nicht aufgerufen wird, sind:

  1. Wenn Sie System.exit() aufrufen
  2. Wenn Sie Runtime.getRuntime().halt(exitStatus) aufrufen
  3. Wenn die JVM zuerst abstürzt
  4. Wenn die JVM eine Endlosschleife erreicht (oder eine andere nicht unterbrechbare, nicht terminierende Anweisung) im try oder catch Block
  5. Wenn das Betriebssystem den JVM-Prozess zwangsweise beendet; z. B. kill -9 auf UNIX
  6. Wenn das Host-System abstürzt; z. B. Stromausfall, Hardwarefehler, OS-Panik usw.
  7. Wenn der finally Block von einem Daemon-Thread ausgeführt werden soll und alle anderen nicht-Deamon-Threads vor dem Aufruf von finally beendet werden

47 Stimmen

Eigentlich thread.stop() verhindert nicht unbedingt finally Block nicht ausgeführt wird.

216 Stimmen

Wie wäre es, wenn wir sagen, dass die finally Block wird aufgerufen après le site try Block, und avant Die Kontrolle geht an die folgenden Anweisungen über. Dies steht im Einklang mit dem try-Block, der eine Endlosschleife beinhaltet, und daher wird der finally-Block nie wirklich aufgerufen.

0 Stimmen

Nach der Definition von @andrzejDoyle wird es zurückgegeben success bevor Sie zu finally blockieren. Ist das richtig?

628voto

Kevin Punkte 6534

Beispielcode:

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

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

Ausgabe:

etwas wird gedruckt. 
0

22 Stimmen

Zu Ihrer Information: In C# ist das Verhalten identisch, abgesehen von der Tatsache, dass das Ersetzen der Anweisung in der finally -Klausel mit return 2; ist nicht erlaubt (Compiler-Fehler).

15 Stimmen

Dies ist ein wichtiges Detail, auf das Sie achten sollten: stackoverflow.com/a/20363941/2684342

0 Stimmen

WENN SIE EINEN CATCH-BLOCK HINZUFÜGEN, error: missing return statement

428voto

MooBob42 Punkte 4155

Auch wenn es eine schlechte Praxis ist, hat ein return-Statement innerhalb des finally-Blocks Vorrang vor einem anderen return aus dem regulären Block. Das folgende Beispiel würde also false zurückgeben:

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

Gleiches gilt für das Werfen von Ausnahmen aus dem finally-Block.

106 Stimmen

Das ist eine WIRKLICH schlechte Praxis. Siehe stackoverflow.com/questions/48088/ für weitere Informationen darüber, warum das schlecht ist.

23 Stimmen

Einverstanden. Eine Rückkehr innerhalb von finally{} ignoriert jede in try{} geworfene Ausnahme. Beängstigend!

1 Stimmen

Egal was passiert, ich habe immer NUR EINEN return Anweisung in meinen Methoden (die am Ende steht), außer wenn die void . Das hat man mir in der Schule beigebracht, und ich denke, das ist auch die bessere Methode.

265voto

polygenelubricants Punkte 362173

Hier sind die offiziellen Worte aus der Java Language Specification.

14.20.2. Ausführung von try-finally und try-catch-finally

Ein try-Anweisung mit einem finally-Block wird ausgeführt, indem zuerst der try-Block ausgeführt wird. Dann gibt es eine Wahl:

  • Wenn die Ausführung des try-Blocks normal abgeschlossen wird, [...]
  • Wenn die Ausführung des try-Blocks abrupt abgebrochen wird wegen eines throw eines Wertes V, [...]
  • Wenn die Ausführung des try-Blocks aus beliebigen anderen Gründen abrupt abgeschlossen wird R, dann wird der finally-Block ausgeführt. Dann gibt es eine Wahl:
    • Wenn der finally-Block normal abgeschlossen wird, wird die try-Anweisung abrupt aus dem Grund R abgeschlossen.
    • Wenn der finally-Block abrupt aus dem Grund S abgeschlossen wird, wird die try-Anweisung abrupt aus dem Grund S abgeschlossen (und Grund R wird verworfen).

Die Spezifikation für return macht dies tatsächlich explizit:

JLS 14.17 Die return-Anweisung

ReturnStatement:
     return Expression(opt) ;

Ein return-Anweisung ohne Expression versucht, die Steuerung an den Aufrufer der Methode oder des Konstruktors zu übertragen, die sie enthält.

Eine return-Anweisung mit einer Expression versucht, die Steuerung an den Aufrufer der Methode zu übertragen, die sie enthält; der Wert des Expression wird zum Wert des Methodenaufrufs.

Die vorherigen Beschreibungen sagen "versucht, die Steuerung zu übertragen" anstatt einfach "überträgt die Steuerung", weil wenn es irgendwelche try-Anweisungen innerhalb der Methode oder des Konstruktors gibt, deren try-Blöcke die return-Anweisung enthalten, dann werden alle finally-Klauseln dieser try-Anweisungen, von innerster zu äußerster, in Reihenfolge ausgeführt, bevor die Steuerung an den Aufrufer der Methode oder des Konstruktors übertragen wird. Ein abruptes Ende einer finally-Klausel kann die Steuerungsübertragung, die durch eine return-Anweisung initiiert wurde, stören.

174voto

Eyal Schneider Punkte 21626

Zusätzlich zu den anderen Antworten ist es wichtig darauf hinzuweisen, dass 'finally' das Recht hat, jede Ausnahme/returned value des try..catch-Blocks zu überschreiben. Zum Beispiel gibt der folgende Code 12 zurück:

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

Ebenso wirft die folgende Methode keine Ausnahme:

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

Während die folgende Methode es wirft:

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

69 Stimmen

Es sollte angemerkt werden, dass der mittlere Fall genau der Grund ist, warum eine Return-Anweisung innerhalb eines finally-Blocks absolut schrecklich ist (es könnte jedes Throwable verstecken).

3 Stimmen

Wer nicht wollen eine unterdrückte OutOfMemoryError ? ;)

0 Stimmen

Ich habe es getestet und es unterdrückt einen solchen Fehler (yipes!). Es erzeugt auch eine Warnung, wenn ich es kompiliere (juhu!). Und man kann es umgehen, indem man eine Rückgabevariable definiert und dann return retVal après le site finally Block, obwohl das natürlich voraussetzt, dass Sie einige andere Ausnahmen unterdrückt haben, weil der Code sonst keinen Sinn machen würde.

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