Wyjątek Javy nie został złapany?
Mam mały teoretyczny problem z konstrukcjami try-catch.
Wczoraj zdałem egzamin praktyczny na temat Javy i nie rozumiem poniższego 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 będzie to AB2C3, ale niespodzianka niespodzianka, to nieprawda.
Właściwą odpowiedzią jest ABC3(testowany i tak naprawdę jest).
Moje pytanie brzmi, gdzie poszedł wyjątek("2")?
6 answers
Ze specyfikacji języka Java 14.20.2.:
Jeśli blok catch zakończy się nagle z powodu R, to blok finally zostanie wykonany. Wtedy jest wybór:
Jeśli blok finally zakończy się normalnie, Instrukcja TRY zakończy się nagle z powodu r.
Jeśli blok finally zakończy się nagle z powodu s, to Instrukcja try zakończy się nagle z powodu s (a przyczyna R jest odrzucone) .
Więc, gdy jest blok catch, który rzuca wyjątek:
try {
// ...
} catch (Exception e) {
throw new Exception("2");
}
Ale jest też blok finally, który również rzuca wyjątek:
} finally {
throw new Exception("3");
}
Exception("2")
zostaną odrzucone i tylko Exception("3")
będą propagowane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-17 13:01:11
Wyjątki rzucone w bloku finally block tłumią wyjątek rzucony wcześniej w bloku try lub catch.
Java 7 przykład: http://ideone.com/0YdeZo
Z Javadoc ' s przykład:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Jednak w tym przykładzie, jeśli metody readLine I close oba rzucają WYJĄTKÓW, wtedy metoda readFirstLineFromFileWithFinallyblock rzuca wyjątek wyrzucony z bloku finally; wyjątek wyrzucony z bloku try jest stłumiony.
Nowa składnia try-with
Java 7 dodaje kolejny krok eliminowania WYJĄTKÓW: wyjątki rzucone w bloku try tłumią te rzucone wcześniej w części try-with.
Z tego samego przykładu:
try (
java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {
String newLine = System.getProperty("line.separator");
String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
Wyjątek może być wyrzucony z bloku kodu związanego z try-with-resources oświadczenie. W powyższym przykładzie wyjątek może być wyrzucone z bloku try, a do dwóch WYJĄTKÓW mogą być wyrzucane z try-with-resources oświadczenie, gdy próbuje zamknąć Obiekty ZipFile i BufferedWriter. Jeśli wyjątek zostanie wyrzucony z try block i jeden lub więcej wyjątków jest wyrzucanych z try-with-resources, wtedy te wyjątki wyrzucone z instrukcje try-with-resources są tłumione, a wyjątek wyrzucany przez blok jest ten, który jest wyrzucany przez metoda writeToFileZipFileContents. Możesz odzyskać te stłumione wyjątki wywołując Throwable.metoda getSuppressed z wyjątek rzucony przez blok try.
W kodzie z question, każdy blok wyraźnie odrzuca stary wyjątek, nawet go nie loguje, nie jest to dobre, gdy próbujesz rozwiązać niektóre błędy:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-08 08:26:13
Ponieważ {[1] } jest wyrzucany z catch
bloku, a nie try
, nie zostanie ponownie złapany.
Zob. 14.20.2. Wykonanie try-finally I try-catch-finally.
Oto co się dzieje:
try {
try {
System.out.print("A"); //Prints A
throw new Exception("1");
} catch (Exception e) {
System.out.print("B"); //Caught from inner try, prints B
throw new Exception("2");
} finally {
System.out.print("C"); //Prints C (finally is always executed)
throw new Exception("3");
}
} catch (Exception e) {
System.out.print(e.getMessage()); //Prints 3 since see (very detailed) link
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-08 07:00:39
Twoje pytanie jest bardzo oczywiste, a odpowiedź jest prosta w tym samym stopniu.. obiekt wyjątku z wiadomością jako " 2 "jest nadpisywany przez obiekt wyjątku z wiadomością jako" 3".
Explanation: Gdy wystąpi wyjątek, jego obiekt rzuca się złapać blok do obsługi. Ale gdy wyjątek występuje w samym bloku catch, jego obiekt jest przenoszony do zewnętrznego bloku CATCH (jeśli istnieje) w celu obsługi wyjątków. I to samo stało się tutaj. Obiekt Exception z Komunikatem "2" zostaje przeniesione do zewnętrznego bloku zaczepu . ale czekaj .. Przed opuszczeniem wewnętrznego bloku try-catch musi on w końcu wykonać. Tutaj nastąpiła zmiana, o którą się martwimy. Zostanie wyrzucony nowy obiekt wyjątku(z wiadomością "3") lub ten ostatecznie blok, który zastąpił już wyrzucony obiekt wyjątku (z wiadomością "2").w wyniku czego , podczas wypisywania wiadomości obiektu wyjątku, otrzymaliśmy nadpisaną wartość tzn. "3" a nie "2".
Pamiętaj :tylko jeden obiekt wyjątku może być / align = "left" /
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-07 13:57:01
Blok finally
zawsze działa. Albo ty return
z wewnątrz bloku try, albo wyjątek jest wyrzucany. Wyjątek rzucony w bloku finally
nadpisze wyjątek rzucony w gałęzi catch.
Dodatkowo, wyrzucenie wyjątku nie spowoduje żadnego wyjścia. Linia throw new Exception("2");
niczego nie napisze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-07 07:51:08
Według Twojego kodu:
try {
try {
System.out.print("A");
throw new Exception("1"); // 1
} catch (Exception e) {
System.out.print("B"); // 2
throw new Exception("2");
} finally { // 3
System.out.print("C"); // 4
throw new Exception("3");
}
} catch (Exception e) { // 5
System.out.print(e.getMessage());
}
Jak widać tutaj:
- print A and throws exception
# 1
; - ten wyjątek został przechwycony przez polecenie catch i wydrukuj
B - # 2
; - block finally
# 3
wykonuje polecenie try-catch (lub tylko try, jeśli nie wystąpił żaden wyjątek) i wypisujeC - # 4
i wyrzuca nowy wyjątek; - ten został złapany przez zewnętrzne stwierdzenie catch
# 5
;
Wynik to ABC3
. I 2
jest pominięte w tak samo jak 1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-13 22:40:24