Biorąc pod uwagę ten kod, czy mogę być absolutnie pewien, że finally
blok zawsze wykonuje się, bez względu na to, co something()
jest?
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 Five
źródło
źródło
probably
.finally
; finalizator ==finalize()
metoda.Odpowiedzi:
Tak,
finally
zostanie wywołany po wykonaniu blokówtry
lubcatch
kodu.Jedyne czasy,
finally
które nie zostaną wywołane, to:System.exit()
Runtime.getRuntime().halt(exitStatus)
try
lubcatch
kill -9 <pid>
w systemie UNIXfinally
blok ma być wykonywany przez wątek demona, a wszystkie inne wątki inne niż demony wychodzą przedfinally
wywołaniemźródło
thread.stop()
niekoniecznie uniemożliwia wykonaniefinally
bloku.finally
blok będzie wywoływana po tymtry
bloku i przed kontrola przechodzi się do następujących stwierdzeń. Jest to zgodne z blokiem try obejmującym nieskończoną pętlę, a zatem blok w końcu nigdy nie jest faktycznie wywoływany.Przykładowy kod:
Wynik:
źródło
finally
klauzuli na-return 2;
jest niedozwolona (błąd kompilatora).Ponadto, chociaż jest to zła praktyka, jeśli w ostatnim bloku znajduje się instrukcja return, przewyższy ona każdy inny zwrot ze zwykłego bloku. Oznacza to, że następujący blok zwróciłby wartość false:
To samo dotyczy rzucania wyjątków od bloku w końcu.
źródło
Oto oficjalne słowa ze specyfikacji języka Java.
14.20.2. Wykonanie try-wreszcie i try-catch-wreszcie
Specyfikacja dla
return
tego wyraźnie wyjaśnia:JLS 14.17 Deklaracja zwrotu
źródło
Oprócz innych odpowiedzi ważne jest, aby zaznaczyć, że „w końcu” ma prawo nadpisać wszelkie wyjątki / zwrócone wartości przez blok try..catch. Na przykład następujący kod zwraca 12:
Podobnie poniższa metoda nie zgłasza wyjątku:
Podczas gdy następująca metoda go wyrzuca:
źródło
OutOfMemoryError
? ;)return retVal
po tymfinally
bloku, mimo że oczywiście zakłada, że tłumione kilka innych wyjątków, ponieważ kod nie ma sensu inaczej.Próbowałem powyższy przykład z niewielką modyfikacją
Powyższy kod generuje:
Wynika to z tego, że kiedy
return i;
jest wykonywany,i
ma wartość 2. Po tymfinally
wykonywany jest blok, do którego przypisano 12,i
a następnieSystem.out
wykonywany jest out.Po wykonaniu
finally
blokutry
blok zwraca 2 zamiast 12, ponieważ ta instrukcja return nie jest wykonywana ponownie.Jeśli będzie debugowania tego kodu w Eclipse wtedy dostaniesz wrażenie, że po wykonaniu
System.out
zfinally
blokowaniareturn
oświadczenietry
bloku jest ponownie wykonywane. Ale tak nie jest. Zwraca po prostu wartość 2.źródło
i
nie byłby prymitywnym, ale obiektem całkowitym.Oto opracowanie odpowiedzi Kevina . Ważne jest, aby wiedzieć, że wyrażenie, które ma zostać zwrócone, jest oceniane wcześniej
finally
, nawet jeśli jest zwracane później.Wynik:
źródło
finally
. Obliczanie wartości zwracanej (printX()
tutaj) jest jeszcze przed nią.System.out.println("finally trumps return... sort of");
przezSystem.out.print("finally trumps return in try"); return 42;
To cała idea ostatecznego bloku. Pozwala upewnić się, że robisz porządki, które w przeciwnym razie mogą zostać pominięte, ponieważ wracasz, między innymi, oczywiście.
W końcu zostaje wywołany niezależnie od tego, co dzieje się w bloku try ( chyba że zadzwonisz
System.exit(int)
lub maszyna wirtualna Java zostanie uruchomiona z innego powodu).źródło
Logicznym sposobem myślenia na ten temat jest:
źródło
ostatecznie jest zawsze wykonywane, chyba że wystąpi nieprawidłowe zakończenie programu (np. wywołanie System.exit (0) ..). więc twój sysout zostanie wydrukowany
źródło
Również powrót w końcu odrzuci każdy wyjątek. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
źródło
Ostatecznie blok jest zawsze wykonywany, chyba że wystąpi nienormalne zakończenie programu, wynikające z awarii JVM lub wywołania
System.exit(0)
.Ponadto, każda wartość zwrócona z bloku ostatecznie zastąpi wartość zwróconą przed wykonaniem bloku ostatecznie, więc należy uważać na wszystkie punkty wyjścia podczas korzystania z try wreszcie.
źródło
Nie, nie zawsze jeden wyjątek to // System.exit (0); zanim blok w końcu uniemożliwia w końcu wykonanie.
źródło
Wreszcie zawsze uruchamiane jest to o to chodzi, tylko dlatego, że pojawia się w kodzie po powrocie, nie oznacza, że tak jest zaimplementowane. Środowisko wykonawcze Java jest odpowiedzialne za uruchomienie tego kodu podczas wychodzenia z
try
bloku.Na przykład, jeśli masz następujące elementy:
Środowisko wykonawcze wygeneruje coś takiego:
Jeśli zgłoszony zostanie nieprzechwycony wyjątek,
finally
blok zostanie uruchomiony, a wyjątek będzie kontynuowany.źródło
Jest tak, ponieważ przypisałeś wartość i jako 12, ale nie zwróciłeś wartości i do funkcji. Prawidłowy kod jest następujący:
źródło
Ponieważ ostatecznie blok będzie zawsze wywoływany, chyba że zadzwonisz
System.exit()
(lub wątek się zawiesi).źródło
Krótko mówiąc, w oficjalnej dokumentacji Java (kliknij tutaj ) napisano, że -
źródło
WEJŚCIE:
WYNIK:
źródło
Tak, zostanie wywołany. Taki jest sens posiadania wreszcie słowa kluczowego. Jeśli wyskakiwanie z bloku try / catch może po prostu pominąć blok ostatecznie, to to samo, co umieszczenie pliku System.out.println poza try / catch.
źródło
Tak, w końcu blok jest zawsze wykonywany. Większość programistów używa tego bloku do zamykania połączenia z bazą danych, obiektu wynikowego, obiektu instrukcji, a także używa hibernacji java do wycofania transakcji.
źródło
NIE ZAWSZE
Specyfikacja języka Java opisuje sposób
try
-catch
-finally
itry
-catch
bloki pracują w 14.20.2W żadnym miejscu nie określa, że
finally
blok jest zawsze wykonywany. Jednak we wszystkich przypadkach, w którychtry
-catch
-finally
itry
-finally
bloki zakończyć to jednak określić, że przed zakończeniemfinally
muszą być wykonywane.JLS nie gwarantuje wykonania FIN po kodzie . JLS gwarantuje, że jeśli zostaną wykonane KOD i NASTĘPNY, to FIN będzie zawsze wykonywany po KOD i przed NASTĘPNYM .
Dlaczego JLS nie gwarantuje, że
finally
blok jest zawsze wykonywany potry
bloku? Ponieważ to niemożliwe. Jest mało prawdopodobne, ale możliwe, że JVM zostanie przerwana (zabijanie, awaria, wyłączenie zasilania) tuż po ukończeniutry
bloku, ale przed wykonaniemfinally
bloku. JLS nie może nic zrobić, aby tego uniknąć.Zatem każde oprogramowanie, które dla ich prawidłowego zachowania zależy od
finally
bloków zawsze wykonywanych po ichtry
ukończeniu, jest błędne.return
instrukcje wtry
bloku nie mają znaczenia dla tego problemu. Jeśli wykonanie osiągnie kod potry
-catch
-finally
jest zagwarantowane, żefinally
blok zostanie wykonany przedreturn
instrukcją wewnątrztry
bloku lub bez niego .źródło
Tak, to będzie. Bez względu na to, co się stanie w bloku try lub catch, chyba że wywołano System.exit () lub JVM uległo awarii. jeśli w bloku (blokach) znajduje się jakaś instrukcja return, ostatecznie zostanie wykonana przed tą instrukcją return.
źródło
Tak, to będzie. Tylko, że tak nie będzie, JVM kończy działanie lub ulega awarii
źródło
Dodanie do odpowiedzi @ vibhash, ponieważ żadna inna odpowiedź nie wyjaśnia, co dzieje się w przypadku obiektu zmiennego, takiego jak ten poniżej.
Wyjdzie
źródło
Próbowałem tego, jest to jednowątkowy.
main
Thread
Będzie nawait
stanie na zawsze, a więcfinally
nigdy nie zostanie wywołana ,więc wyjście konsoli nie będzie
print
String
: powait()
lubfinally
Powyższy przykład, uzgodniony z @Stephen C, jest jedną z 3. wzmianek o przypadkach tutaj :
Dodanie kilku takich możliwości nieskończonej pętli w następującym kodzie:
Przypadek 2: Jeśli JVM ulegnie awarii w pierwszej kolejności
Ref: W jaki sposób zawiesisz JVM?
Przypadek 6: Jeśli
finally
blok ma być wykonywany przez demonaThread
i wszystkie inneThreads
wyjścia inne niż demony przedfinally
wywołaniem.wyjście: To nie drukuje „w końcu”, co sugeruje, że „W końcu blok” w „wątku demona” nie został wykonany
źródło
Rozważ następujący program:
Od wersji Java 1.8.162 powyższy blok kodu daje następujące dane wyjściowe:
oznacza to, że używanie
finally
do zwalniania obiektów jest dobrą praktyką, taką jak następujący kod:źródło
sb.setLength(0)
wreszcie?sb = null;
dodaje niepotrzebny kod. Rozumiem, że masz na myśli, żefinally
blok jest dobrym miejscem do zwolnienia zasobów, takich jak połączenie z bazą danych lub coś takiego, ale pamiętaj, że twój przykład może wprowadzać zamieszanie w nowych.System.out.println("---AGAIN2---");
System.out.println(sb);
i jest teraz bardziej przejrzyste. W tej chwili wynik był niezgodny z twoją tezą: p Dodałem również do twojej odpowiedzi, ale zmiana musi zostać zaakceptowana przez moderatora lub kogoś takiego. W przeciwnym razie możesz je dodaćTak naprawdę jest to prawdą w każdym języku ... w końcu zawsze będzie wykonywane przed instrukcją return, bez względu na to, gdzie zwrot ten znajduje się w treści metody. Gdyby tak nie było, blok w końcu nie miałby większego znaczenia.
źródło
Oprócz kwestii powrotu do ostatecznego zastąpienia zwrotu w bloku try, to samo dotyczy wyjątku. Wreszcie blok, który zgłasza wyjątek, zastąpi zwrot lub wyjątek zgłoszony z bloku try.
źródło
finally
wykona się i to na pewno.finally
nie będzie działać w poniższych przypadkach:przypadek 1 :
Podczas wykonywania
System.exit()
.przypadek 2:
Gdy następuje awaria JVM / wątku.
przypadek 3:
Gdy wykonanie zostanie zatrzymane pomiędzy nimi ręcznie.
źródło
źródło