Spielt es bei try/finally eine Rolle, was im try enthalten ist?
-
20-12-2019 - |
Frage
Gibt es einen funktionalen Unterschied?
Connection c = null;
try {
c = getConnection();
c.doStuff();
} finally {
if (c!=null) c.close();
}
vs
Connection c = null;
c = getConnection();
c.doStuff();
try {
} finally {
if (c!=null) c.close();
}
vs
Connection c = null;
try {
c = getConnection();
} finally {
if (c!=null) c.close();
}
c.doStuff();
Ich habe das Gefühl, dass sie alle in jedem Fall das Gleiche tun werden
Lösung
Eine Ausnahme, die außerhalb von a auftritt try-finally
Block ist per Definition ein unbehandelte Ausnahme.In diesem Fall haben Sie keine Garantie dafür, wie das Betriebssystem oder die Laufzeit damit umgehen.Die Chancen stehen gut, dass keine Ausnahmeabwicklung ausgelöst wird, Ihr Code einfach abbricht (vielleicht beschreibt abend es in dieser Diskussion besser – „abnormales Ende“), und Ihr Code wird einfach abgebrochen finally
Block wird niemals ausgeführt.
Der Punkt von try-finally
soll garantieren, dass die Codebereinigung erfolgt, und zwar im richtigen Kontext.
Sie müssen denken, dass der Code in der finally
Der Block wird immer ausgeführt, egal was passiert, und er wird ausgeführt, nachdem die gesamte Methode abgeschlossen ist. Daher spielt es keine Rolle, ob sich der andere Code innerhalb oder außerhalb des Blocks befindet try-finally
konstruieren, aber das ist nicht korrekt.
Wenn Sie also Laufzeitgarantien für korrektes Verhalten wünschen, ist Ihr erstes Beispiel das einzig richtige.
In Ihrem ersten Beispiel erwerben Sie und was noch wichtiger ist verwenden eine Verbindung (zu einer Datenbank, würde man annehmen) innerhalb der
try
Block.Wenn eine Ausnahme innerhalb der auftritttry
Block, dann diefinally
Der Block wird ausgeführt und Ihre Verbindung geschlossen.In Ihrem zweiten Beispiel wird Ihr Anschluss komplett außerhalb des erfasst und genutzt
try-catch
bauen.Wenn bei der Verbindung eine Ausnahme auftritt, wird wahrscheinlich der gesamte Kontext verworfenfinally
Der Block wird nicht ausgeführt und Ihre Verbindung wird nicht geschlossen.In Ihrem dritten Beispiel:
finally
wird danach ausgeführttry
, aber vor jedem Code, der nach dem kommtfinally
Block.Beim Versuch, die Verbindung zu verwenden, wird eine Ausnahme generiert, da die Verbindung bereits explizit geschlossen wurde.
Andere Tipps
craig hat sich bereits an das unbehandelte Ausnahmeproblem angesprochen, aber ich wollte es klarstellen.Ich habe zwei Beispiele kodiert (das letzte ist nur schlecht, weil Sie mit einer unterbrochenen Verbindung nach einer Ausnahme arbeiten könnten, nicht wahr werden).Hier ist ein einfaches Beispiel, das einen ArrayIndexoutoNoundsexception auswirkt:
generasacodicetagpre.und hier ist die Ausführung:
generasacodicetagpre.Wie Sie in der ersten Version sehen können, wurde ein Ausnahmet-Handler registriert, da die Ausnahme im Kontext eines Versuchsblocks aufgetreten ist.In der zweiten Version gab es keinen registrierten Ausnahmehandler und der Standardausnahme-Handler wurde aufgerufen (dh eine nicht erfasste Ausnahme).