El akzeptierte Antwort ist in fast allen Aspekten wahr, aber es ist trotzdem nur die halbe Wahrheit (ok, 95% der Wahrheit).
Gehen Sie von folgendem Code aus:
private final Lock m_Lock = new ReentrantLock();
…
public final SomeObject doSomething( final SomeObject arg )
{
final SomeObject retValue;
try
{
lock.lock();
retValue = SomeObject( arg );
}
finally
{
out.println( "Entering finally block");
callingAnotherMethod( arg, retValue );
lock.unlock();
}
return retValue;
}
…
try
{
final var result = doSomething( new SomeObject() );
}
catch( final StackOverflowError e ) { /* Deliberately ignored */ }
Aufruf der Methode doSomething()
wird eine StackOverflowError
fast sofort.
Und die lock
wird nicht veröffentlicht!
Aber wie konnte dies geschehen, wenn die finally
Block wird immer ausgeführt (mit den Ausnahmen, die bereits in der akzeptierte Antwort )?
Das liegt daran, dass es eine keine Garantie gemacht, dass alle Aussagen im finally
Block sind wirklich ausgeführt!
Dies wäre offensichtlich, wenn es einen Aufruf zu System.exit()
oder eine throws
Anweisung vor dem Aufruf von lock.unlock()
.
Aber im Beispielcode ist nichts dergleichen zu finden
Abgesehen davon, dass die beiden anderen Methodenaufrufe in der finally
Block vor dem Aufruf von lock.unlock()
wird eine weitere StackOverflowError
Und voilà, die Sperre wird nicht aufgehoben!
Obwohl der Beispielcode an sich albern ist, lassen sich ähnliche Muster in vielen Arten von Software finden. Alles funktioniert gut, solange nichts Hässliches in der finally
blockieren
Lustige Tatsache ist, dass es nicht funktioniert in späteren Versionen von Java (was bedeutet, dass in späteren Versionen, die Sperre wurde freigegeben ). Keine Ahnung, wann und warum dies geändert.
Aber Sie müssen trotzdem sicherstellen, dass die finally
Block immer normal beendet wird, sonst könnte es egal sein, ob (dass) er immer ausgeführt wird
672 Stimmen
Wenn dies nicht der Fall ist, sollte das Schlüsselwort wie folgt lauten
probably
stattdessen.61 Stimmen
Nicht siempre
3 Stimmen
Effektives Java sagt etwas anderes informit.com/articles/article.aspx?p=1216151&seqNum=7
38 Stimmen
@BinoyBabu, Abschlussbericht !=
finally
; Abschlussbericht \== diefinalize()
Methode.5 Stimmen
@Boann Richtig, "nicht immer" in der Tat. Aber dann können Sie nie und nimmer die Worte "garantiert" oder "immer" verwenden.
2 Stimmen
@Boann Ich würde es so formulieren: Der Ausführungsfluss geht immer durch finally, bevor er die try-finally-Struktur verlässt. Wenn er darin stirbt, ist das für mich in Ordnung, denn der Hauptzweck von finally ist es, sicherzustellen, dass die Dinge für andere Teile des Codes nicht durcheinander gebracht werden.
0 Stimmen
Sieht aus, als hättest du da einen ganz schönen Fisch gefangen!
0 Stimmen
Wenn die
finally
Block einen Wert zurückgibt, dann kann der try/catch-Block nicht zurückkehren.0 Stimmen
@NoonSilk Das war saukomisch!