Ich war kürzlich überrascht, dass es möglich ist, eine return-Anweisung in einem finally-Block in Java zu haben.
Es scheint, als ob viele Leute denken, dass es eine schlechte Sache ist, wie in " Nicht in einer finally-Klausel zurückkehren " beschrieben. Als ich etwas tiefer kratzte, fand ich auch " Javas Rückkehr ist nicht immer ", was einige ziemlich schreckliche Beispiele für andere Arten der Flusskontrolle in endgültigen Blöcken zeigt.
Meine Frage ist also, kann mir jemand ein Beispiel geben, bei dem eine return-Anweisung (oder eine andere Flusskontrolle) in einem finally-Block besseren / besser lesbaren Code erzeugt?
quelle
Ich hatte es vor Jahren WIRKLICH schwer, einen Fehler aufzuspüren, der dadurch verursacht wurde. Der Code war so etwas wie:
Was passiert ist, ist, dass die Ausnahme in einem anderen Code abgeworfen wurde. Es wurde innerhalb der
somethingThatThrewAnException()
Methode gefangen und protokolliert und erneut geworfen . Aber die Ausnahme wurde nicht in der Vergangenheit verbreitetproblemMethod()
. Nach einer langen Zeit, in der wir uns das angesehen haben, haben wir es endlich bis zur Rückgabemethode aufgespürt. Die Rückgabemethode im finally-Block hat im Grunde genommen verhindert, dass sich die im try-Block aufgetretene Ausnahme ausbreitet, obwohl sie nicht abgefangen wurde.Wie andere gesagt haben, ist es zwar legal, von einem endgültigen Block gemäß der Java-Spezifikation zurückzukehren, aber es ist eine SCHLECHTE Sache und sollte nicht getan werden.
quelle
javac warnt vor der endgültigen Rückgabe, wenn Sie -Xlint: finally verwenden. Ursprünglich gab javac keine Warnungen aus - wenn etwas mit dem Code nicht stimmt, sollte er nicht kompiliert werden können. Leider bedeutet Abwärtskompatibilität, dass unerwartete geniale Dummheit nicht verboten werden kann.
Ausnahmen können von endgültigen Blöcken geworfen werden, aber in diesem Fall ist das gezeigte Verhalten mit ziemlicher Sicherheit das, was Sie wollen.
quelle
Das Hinzufügen von Kontrollstrukturen und die Rückkehr zu finally {} -Blöcken sind nur ein weiteres Beispiel für Missbräuche, die in praktisch allen Entwicklungssprachen verstreut sind. Jason hat zu Recht vorgeschlagen, dass es leicht zu einem Alptraum für die Instandhaltung werden könnte - die Argumente gegen vorzeitige Rückgaben von Funktionen gelten eher für diesen Fall von "verspäteten Rückgaben".
Schließlich gibt es Blöcke für einen Zweck, damit Sie vollständig aufräumen können, unabhängig davon, was im gesamten vorhergehenden Code passiert ist. Im Prinzip geht es darum, Dateizeiger, Datenbankverbindungen usw. zu schließen / freizugeben, obwohl ich sehen konnte, dass es gestreckt ist, das Hinzufügen einer maßgeschneiderten Prüfung zu sagen.
Alles, was die Rückgabe der Funktion beeinflusst, sollte im try {} -Block liegen. Selbst wenn Sie eine Methode hätten, mit der Sie einen externen Status überprüft, eine zeitaufwändige Operation ausgeführt und diesen Status dann erneut überprüft haben, falls er ungültig wird, möchten Sie dennoch die zweite Überprüfung im try {} - wenn sie sich schließlich im Inneren befindet {} Wenn die lange Operation fehlgeschlagen ist, würden Sie diesen Status ein zweites Mal unnötig überprüfen.
quelle
Ein einfacher Groovy-Test:
Ausgabe:
Frage:
Ein interessanter Punkt für mich war zu sehen, wie Groovy mit impliziten Renditen umgeht. In Groovy ist es möglich, von einer Methode "zurückzukehren", indem einfach ein Wert am Ende verbleibt (ohne Rückgabe). Was denkst du passiert, wenn du das auskommentierst? Zeile runningThreads.remove (..) in der finally-Anweisung auskommentieren - wird dadurch der reguläre Rückgabewert ("OK") überschrieben und die Ausnahme abgedeckt?!
quelle
Wenn Sie aus einem
finally
Block zurückkehren, gehtexceptions
dies verloren.Eine return-Anweisung in einem finally-Block führt dazu, dass alle Ausnahmen, die möglicherweise im try- oder catch-Block ausgelöst werden, verworfen werden.
Gemäß der Java-Sprachspezifikation:
Hinweis: Gemäß JLS 14.17 wird eine return-Anweisung immer abrupt abgeschlossen.
quelle