Może się to wydawać pytaniem o programowanie 101 i myślałem, że znam odpowiedź, ale teraz muszę sprawdzić dwukrotnie. W tym fragmencie kodu poniżej, czy wyjątek rzucony w pierwszym bloku catch zostanie następnie przechwycony przez ogólny blok Exception catch poniżej?
try {
// Do something
} catch(IOException e) {
throw new ApplicationException("Problem connecting to server");
} catch(Exception e) {
// Will the ApplicationException be caught here?
}
Zawsze myślałem, że odpowiedź brzmi: nie, ale teraz mam dziwne zachowanie, które może być przez to spowodowane. Odpowiedź jest prawdopodobnie taka sama dla większości języków, ale pracuję w Javie.
Odpowiedzi:
Nie, ponieważ nowy
throw
nie znajduje siętry
bezpośrednio w bloku.źródło
RuntimeException
zostanie wyrzucony zcatch
bloku, nie wystąpi błąd kompilacji.catch
klauzula wyjątku nadrzędnego zostanie wymieniona przedcatch
klauzulą wyjątku podrzędnego . Rozumiem, że Java na to nie zezwala i jest przechwytywana w czasie kompilacji.Nie. Bardzo łatwo to sprawdzić.
Powinien wydrukować:
Z technicznego punktu widzenia mógł to być błąd kompilatora, zależne od implementacji, nieokreślone zachowanie lub coś w tym rodzaju. Jednak JLS jest dość dobrze dopracowany, a kompilatory są wystarczająco dobre do tego rodzaju prostych rzeczy (przypadek narożnika generycznego może być inną sprawą).
Zauważ również, że jeśli zamienisz się dwoma blokami catch, to się nie skompiluje. Drugi haczyk byłby całkowicie nieosiągalny.
Zauważ, że ostatni blok zawsze działa, nawet jeśli wykonywany jest blok catch (poza głupimi przypadkami, takimi jak nieskończone pętle, dołączanie przez interfejs narzędzi i zabijanie wątku, przepisywanie kodu bajtowego itp.).
źródło
finally
jest oczywiście sprawdzenieSystem.exit
. :-Pfor(;;);
jest krótszy, zawarty w języku, nie wprowadza zbytnio efektów ubocznych i dla mnie jest bardziej oczywisty.System.exit
jest bardziej przyjazny dla procesora! : -O Ale tak, ok, oczywiście jest to kryterium subiektywne. Nie wiedziałem też, że jesteś golfistą szyfrującym. ;-)Specyfikacja języka Java mówi w sekcji 14.19.1:
Źródła : http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#24134
Innymi słowy, pierwszy obejmujący przechwyt, który może obsłużyć wyjątek, robi, a jeśli wyjątek zostanie wyrzucony z tego przechwytywania, nie jest to zakres żadnego innego przechwytywania dla oryginalnej próby, więc nie będą próbowali go obsłużyć.
Jedną z powiązanych i mylących rzeczy, które należy wiedzieć, jest to, że w strukturze try- [catch] -finally blok final może zgłosić wyjątek, a jeśli tak, każdy wyjątek rzucony przez blok try lub catch zostaje utracony. To może być mylące, gdy zobaczysz to po raz pierwszy.
źródło
try
-with-resources. Następnie, jeślitry
ORAZfinally
oba rzutowanie,finally
jest pomijane, ale jest również DODANE do wyjątku odtry
. Jeśli równieżcatch
rzuca, nie masz szczęścia, chyba że sam sobie z tym poradzisz, używając polecenia „addSuppressed” i dodająctry
wyjątek - wtedy masz wszystkie trzy.Jeśli chcesz zgłosić wyjątek z bloku catch, musisz poinformować o tym swoją metodę / klasę / etc. że musi zgłosić wspomniany wyjątek. Tak jak to:
A teraz twój kompilator nie będzie na ciebie krzyczał :)
źródło
Nie - jak powiedział Chris Jester-Young, zostanie on wyrzucony do następnego próbnego złapania w hierarchii.
źródło
Jak wspomniano powyżej ...
dodam, że jeśli masz problem z zobaczeniem, co się dzieje, jeśli nie możesz odtworzyć problemu w debugerze, możesz dodać ślad przed ponownym wyrzuceniem nowego wyjątku (z dobrym starym Systemem .out.println co gorsza, z dobrym systemem dzienników, takim jak log4j).
źródło
Nie zostanie złapany przez drugi blok zaczepowy. Każdy wyjątek jest przechwytywany tylko wtedy, gdy znajduje się w bloku próbnym. Możesz jednak zagnieżdżać próby (co nie jest ogólnie dobrym pomysłem):
źródło
Nie, ponieważ wszystkie catch odnoszą się do tego samego bloku try, więc rzucanie z wewnątrz bloku catch zostanie złapane przez otaczający blok try (prawdopodobnie w metodzie, która wywołała ten)
źródło
Stary post, ale zmienna „e” musi być unikalna:
źródło