Kann ich angesichts dieses Codes absolut 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("I don't know if this will get printed out");
}
java
error-handling
return
try-catch-finally
Jonny fünf
quelle
quelle
probably
stattdessen das Schlüsselwort benannt werden.finally
; finalizer == diefinalize()
Methode.Antworten:
Ja,
finally
wird nach der Ausführung dertry
odercatch
Codeblöcke aufgerufen .Die einzigen Zeiten,
finally
die nicht aufgerufen werden, sind:System.exit()
Runtime.getRuntime().halt(exitStatus)
try
oder erreichtcatch
kill -9 <pid>
unter UNIXfinally
Block von einem Daemon-Thread ausgeführt werden soll und alle anderen Nicht-Daemon-Threads, die zuvor beendet wurden,finally
aufgerufen werdenquelle
thread.stop()
Verhindert eigentlich nicht unbedingt diefinally
Ausführung des Blocks.finally
Block nach demtry
Block aufgerufen wird und bevor die Steuerung auf die folgenden Anweisungen übergeht. Dies steht im Einklang mit dem try-Block, der eine Endlosschleife enthält, und daher wird der finally-Block nie tatsächlich aufgerufen.Beispielcode:
Ausgabe:
quelle
finally
Ihrer Information : In C # ist das Verhalten identisch, abgesehen davon, dass das Ersetzen der Anweisung in der -klausel durchreturn 2;
nicht zulässig ist (Compiler-Fehler).Auch wenn es eine schlechte Praxis ist, übertrifft eine return-Anweisung innerhalb des finally-Blocks jede andere return-Anweisung aus dem regulären Block. Das heißt, der folgende Block würde false zurückgeben:
Gleiches gilt für das Auslösen von Ausnahmen aus dem finally-Block.
quelle
Hier sind die offiziellen Wörter aus der Java-Sprachspezifikation.
14.20.2. Ausführung von try-finally und try-catch-finally
Die Spezifikation für
return
macht dies tatsächlich explizit:JLS 14.17 Die Rückgabeerklärung
quelle
Zusätzlich zu den anderen Antworten ist es wichtig darauf hinzuweisen, dass 'finally' das Recht hat, jede Ausnahme / jeden zurückgegebenen Wert durch den try..catch-Block zu überschreiben. Der folgende Code gibt beispielsweise 12 zurück:
In ähnlicher Weise löst die folgende Methode keine Ausnahme aus:
Während die folgende Methode es wirft:
quelle
OutOfMemoryError
? ;)return retVal
nach demfinally
Block verwenden, obwohl dies natürlich davon ausgeht, dass Sie einige andere Ausnahmen unterdrückt haben, da der Code sonst keinen Sinn ergeben würde.Ich habe das obige Beispiel mit geringfügigen Änderungen ausprobiert.
Der obige Code gibt aus:
Dies liegt daran, dass bei
return i;
Ausführungi
ein Wert 2 vorliegt. Danach wird derfinally
Block ausgeführt, dem 12 zugewiesen ist,i
und dannSystem.out
wird ausgeführt.Nach dem Ausführen des
finally
Blocks gibt dertry
Block 2 zurück, anstatt 12 zurückzugeben, da diese return-Anweisung nicht erneut ausgeführt wird.Wenn Sie diesen Code in Eclipse debuggen, haben Sie das Gefühl, dass nach der Ausführung
System.out
vonfinally
block diereturn
Anweisung vontry
block erneut ausgeführt wird. Dies ist jedoch nicht der Fall. Es wird einfach der Wert 2 zurückgegeben.quelle
i
es kein primitives, sondern ein ganzzahliges Objekt wäre?Hier ist eine Ausarbeitung von Kevins Antwort . Es ist wichtig zu wissen, dass der zurückzugebende Ausdruck vorher ausgewertet wird
finally
, auch wenn er danach zurückgegeben wird.Ausgabe:
quelle
finally
. Die Berechnung des Rückgabewerts (printX()
hier) steht noch bevor.System.out.println("finally trumps return... sort of");
durchSystem.out.print("finally trumps return in try"); return 42;
Das ist die ganze Idee eines endgültigen Blocks. Auf diese Weise können Sie sicherstellen, dass Sie Aufräumarbeiten durchführen, die andernfalls möglicherweise übersprungen werden, da Sie unter anderem natürlich zurückkehren.
Wird schließlich aufgerufen, unabhängig davon, was im try-Block passiert (es sei denn, Sie rufen an
System.exit(int)
oder die Java Virtual Machine startet aus einem anderen Grund).quelle
Eine logische Art, darüber nachzudenken, ist:
quelle
Schließlich wird immer ausgeführt, es sei denn, es liegt eine abnormale Programmbeendigung vor (wie das Aufrufen von System.exit (0) ..). Ihr Sysout wird also gedruckt
quelle
Auch eine Rückkehr in wird schließlich jede Ausnahme wegwerfen. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
quelle
Der finally-Block wird immer ausgeführt, es sei denn, es liegt eine abnormale Programmbeendigung vor, die entweder auf einen JVM-Absturz oder auf einen Aufruf von zurückzuführen ist
System.exit(0)
.Darüber hinaus überschreibt jeder Wert, der aus dem finally-Block zurückgegeben wird, den vor der Ausführung des finally-Blocks zurückgegebenen Wert. Überprüfen Sie daher alle Exit-Punkte, wenn Sie try finally verwenden.
quelle
Nein, nicht immer ein Ausnahmefall ist // System.exit (0); bevor der finally-Block verhindert, dass finally ausgeführt wird.
quelle
Schließlich wird immer ausgeführt, das ist der springende Punkt, nur weil es nach der Rückgabe im Code erscheint, heißt das nicht, dass es so implementiert ist. Die Java-Laufzeit hat die Verantwortung, diesen Code beim Verlassen des
try
Blocks auszuführen .Zum Beispiel, wenn Sie Folgendes haben:
Die Laufzeit generiert ungefähr Folgendes:
Wenn eine nicht erfasste Ausnahme ausgelöst wird, wird der
finally
Block ausgeführt und die Ausnahme wird fortgesetzt.quelle
Dies liegt daran, dass Sie den Wert von i als 12 zugewiesen haben, aber den Wert von i nicht an die Funktion zurückgegeben haben. Der richtige Code lautet wie folgt:
quelle
Weil ein finally-Block immer aufgerufen wird, es sei denn, Sie rufen auf
System.exit()
(oder der Thread stürzt ab).quelle
In der offiziellen Java-Dokumentation ( hier klicken ) steht kurz gesagt:
quelle
EINGANG:
AUSGABE:
quelle
Ja, es wird angerufen. Das ist der springende Punkt, um endlich ein Schlüsselwort zu haben. Wenn das Herausspringen aus dem try / catch-Block nur den finally-Block überspringen konnte, war dies dasselbe wie das Platzieren von System.out.println außerhalb des try / catch.
quelle
Ja, schließlich wird der Block immer ausgeführt. Die meisten Entwickler verwenden diesen Block zum Schließen der Datenbankverbindung, des Ergebnismengenobjekts und des Anweisungsobjekts und verwenden ihn auch im Java-Ruhezustand, um die Transaktion zurückzusetzen.
quelle
NICHT IMMER
Die Java - Language - Spezifikation beschreibt , wie
try
-catch
-finally
undtry
-catch
Blöcke an Arbeit 14.20.2Nirgends es gibt an, dass der
finally
Block wird immer ausgeführt. In allen Fällen, in denen die Blöcketry
-catch
-finally
undtry
-finally
vollständig sind, wird jedoch angegeben, dass vor Abschluss die Blöckefinally
ausgeführt werden müssen.Das JLS garantiert nicht, dass FIN nach CODE ausgeführt wird . Das JLS garantiert, dass bei Ausführung von CODE und NEXT FIN immer nach CODE und vor NEXT ausgeführt wird .
Warum garantiert das JLS nicht, dass der
finally
Block immer nach demtry
Block ausgeführt wird? Weil es unmöglich ist. Es ist unwahrscheinlich, aber möglich, dass die JVM unmittelbar nach Abschluss destry
Blocks, jedoch vor der Ausführung desfinally
Blocks abgebrochen wird (Kill, Crash, Power Off) . Das JLS kann nichts tun, um dies zu vermeiden.Daher ist jede Software, die für ihr korrektes Verhalten davon abhängt, dass
finally
Blöcke immer ausgeführt werden, nachdem ihretry
Blöcke vollständig sind, fehlerhaft.return
Anweisungen imtry
Block sind für dieses Problem irrelevant. Wenn die Ausführung nachtry
-catch
- den Code erreichtfinally
, wird garantiert, dass derfinally
Block zuvor mit oder ohnereturn
Anweisungen innerhalb destry
Blocks ausgeführt wurde.quelle
Ja, es wird. Egal, was in Ihrem Try- oder Catch-Block passiert, es sei denn, System.exit () wird aufgerufen oder JVM stürzt ab. Wenn sich in den Blöcken eine return-Anweisung befindet, wird diese schließlich vor dieser return-Anweisung ausgeführt.
quelle
Ja, es wird. Nur wenn dies nicht der Fall ist, wird JVM beendet oder stürzt ab
quelle
Das Hinzufügen zu @ vibhashs Antwort als keine andere Antwort erklärt, was im Fall eines veränderlichen Objekts wie dem folgenden passiert.
Wird ausgegeben
quelle
Ich habe es versucht, es ist Single-Threaded.
Der
main
Thread
wird für immer imwait
Zustand sein, daherfinally
wird er niemals genannt werden ,Die Konsolenausgabe wird also nicht
print
String
: nachwait()
oderfinally
In Übereinstimmung mit @Stephen C ist das obige Beispiel einer der dritten Fälle, die hier erwähnt werden :
Hinzufügen weiterer solcher Endlosschleifenmöglichkeiten im folgenden Code:
Fall 2: Wenn die JVM zuerst abstürzt
Ref: Wie stürzt man eine JVM ab?
Fall 6: Wenn der
finally
Block vom Daemon ausgeführt werden sollThread
und alle anderen Nicht-Daemon-ExitsThreads
zuvorfinally
aufgerufen werden.Ausgabe: Dies gibt nicht "finally" aus, was bedeutet, dass "finally block" im "Daemon-Thread" nicht ausgeführt wurde
quelle
Betrachten Sie das folgende Programm:
Ab Java 1.8.162 gibt der obige Codeblock die folgende Ausgabe aus:
Dies bedeutet, dass das Freigeben
finally
von Objekten eine gute Vorgehensweise wie der folgende Code ist:quelle
sb.setLength(0)
endlich sein?sb = null;
fügt nur nicht benötigten Code hinzu. Ich verstehe, dass Sie meinen, dass einfinally
Block ein guter Ort ist, um Ressourcen wie eine Datenbankverbindung oder ähnliches freizugeben, aber denken Sie daran, dass Ihr Beispiel Neulinge verwirren könnte.System.out.println("---AGAIN2---");
System.out.println(sb);
und es ist jetzt klarer. So wie es war, war die Ausgabe gegen Ihre These: p Ich habe auch zu Ihrer Antwort hinzugefügt, aber die Bearbeitung muss von einem Moderator oder einer ähnlichen Person akzeptiert werden.Das ist tatsächlich in jeder Sprache der Fall ... wird schließlich immer vor einer return-Anweisung ausgeführt, unabhängig davon, wo sich diese return im Methodenkörper befindet. Wenn das nicht der Fall wäre, hätte der finally-Block nicht viel Bedeutung.
quelle
Zusätzlich zu dem Punkt über die Rückgabe beim endgültigen Ersetzen einer Rückgabe im try-Block gilt das Gleiche für eine Ausnahme. Ein finally-Block, der eine Ausnahme auslöst, ersetzt eine Rückgabe oder Ausnahme, die aus dem try-Block ausgelöst wird.
quelle
finally
wird ausgeführt und das ist sicher.finally
wird in den folgenden Fällen nicht ausgeführt:Fall 1 :
Wenn Sie ausführen
System.exit()
.Fall 2:
Wenn Ihre JVM / Thread abstürzt.
Fall 3:
Wenn Ihre Ausführung zwischendurch manuell gestoppt wird.
quelle
quelle