Mam mały problem teoretyczny z konstrukcjami typu try-catch.
Wczoraj zdałem praktyczny egzamin z języka Java i nie rozumiem następującego przykładu:
try {
try {
System.out.print("A");
throw new Exception("1");
} catch (Exception e) {
System.out.print("B");
throw new Exception("2");
} finally {
System.out.print("C");
throw new Exception("3");
}
} catch (Exception e) {
System.out.print(e.getMessage());
}
Pytanie brzmiało "jak będzie wyglądał wynik?"
Byłem prawie pewien, że to będzie AB2C3, ALE niespodzianka, to nieprawda.
Prawidłowa odpowiedź to ABC3 (przetestowane i naprawdę tak jest).
Moje pytanie brzmi: gdzie poszedł wyjątek („2”)?
print(e.getMessage())
:). Pomyślałeś, że wynik będzie następującyAB2C3
: czy sądzisz, że najbardziej zewnętrznycatch
blok zostanie wykonany dwukrotnie?Odpowiedzi:
Ze specyfikacji języka Java 14.20.2. :
Tak więc, gdy istnieje blok catch, który zgłasza wyjątek:
ale jest też ostatni blok, który również zgłasza wyjątek:
Exception("2")
zostaną odrzucone i tylkoException("3")
będą propagowane.źródło
return
stwierdzeń. Jeśli twój ostatni blok ma zwrot, zastąpi on każdy powrót w blokutry
lubcatch
. Ze względu na te „funkcje” dobrą praktyką jest to, aby ostatecznie blok nigdy nie zgłaszał wyjątku ani nie zawierał instrukcji return.Wyjątki zgłoszone w final block pomijają wyjątek zgłoszony wcześniej w bloku try lub catch.
Przykład Java 7: http://ideone.com/0YdeZo
Z przykładu Javadoc :
Nowa
try-with
składnia Java 7 dodaje kolejny krok do pomijania wyjątków: wyjątki zgłoszone w bloku try pomijają te, które zostały wcześniej zgłoszone w części próbnej.z tego samego przykładu:
W kodzie z pytania każdy blok po prostu odrzuca stary wyjątek, nawet go nie rejestruje, co nie jest dobre, gdy próbujesz rozwiązać niektóre błędy:
http://en.wikipedia.org/wiki/Error_hiding
źródło
Ponieważ
throw new Exception("2");
jest wyrzucany zcatch
bloku, a nietry
, nie zostanie ponownie złapany.Patrz 14.20.2. Wykonywanie prób na koniec i wreszcie próba złapania .
Oto, co się dzieje:
źródło
Twoje pytanie jest bardzo oczywiste, a odpowiedź równie prosta. Obiekt Exception z komunikatem „2” jest nadpisywany przez obiekt Exception z komunikatem „3”.
Objaśnienie: Gdy wystąpi wyjątek, jego obiekt jest rzucany w celu złapania bloku do obsłużenia. Ale gdy wyjątek wystąpi w samym bloku catch, jego obiekt jest przenoszony do bloku OUTER CATCH (jeśli istnieje) w celu obsługi wyjątków. I to samo stało się tutaj. Obiekt wyjątku z komunikatem „2” jest przesyłany do bloku OUTER catch. Ale czekaj … Przed opuszczeniem wewnętrznego bloku try-catch MUSI WYKONAĆ OSTATECZNIE. Tutaj nastąpiła zmiana, o którą się martwimy. Zostaje wyrzucony nowy obiekt EXCEPTION (z komunikatem „3”) lub ten ostatecznie blok, który zastąpił już wrzucony obiekt Exception (z komunikatem „2”). W wyniku czego podczas drukowania komunikatu obiektu Exception otrzymaliśmy nadpisana wartość, tj. „3” a nie „2”.
Keep Remember: Tylko jeden obiekt wyjątku może być obsługiwany przez blok CATCH.
źródło
finally
Blok zawsze działa. Albo jesteśreturn
z wewnątrz bloku try, albo wyrzucany jest wyjątek. Wyjątek zgłoszony wfinally
bloku zastąpi wyjątek zgłoszony w gałęzi catch.Ponadto zgłoszenie wyjątku samo w sobie nie spowoduje żadnego wyniku. Linia
throw new Exception("2");
nic nie wypisze.źródło
Według twojego kodu:
Jak widać tutaj:
# 1
;B - # 2
;# 3
wykonywany po instrukcji try-catch (lub tylko try, jeśli nie wystąpił żaden wyjątek) i wyświetlaC - # 4
i rzuca nowy wyjątek;# 5
;Wynik jest
ABC3
. I2
jest pomijany w taki sam sposób jak1
źródło