Исключение Java не поймали?
У меня маленький теоретической проблема с конструкциями try-catch.
вчера я сдал практический экзамен по Java, и я не понимаю следующий пример:
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());
}
вопрос был "как будет выглядеть выход?"
Я был почти уверен, что это будет AB2C3, но удивительно, это неправда.
правильный ответ-ABC3 (проверено и действительно так).
мой вопрос в том, откуда взялся Исключение("2") идут?
6 ответов:
С Спецификация Языка Java 14.20.2.:
если блок catch завершается внезапно по причине R, то выполняется блок finally. Тогда есть выбор:
если блок finally завершается нормально, то оператор try завершается резко по причине R.
если блок finally завершается внезапно по причине S, то оператор try завершается внезапно для причина S (и причина R отбрасывается).
Итак, когда есть блок catch, который выдает исключение:
try { // ... } catch (Exception e) { throw new Exception("2"); }
но есть также блок finally, который также выдает исключение:
} finally { throw new Exception("3"); }
Exception("2")
будут отброшены и толькоException("3")
будут распространяться.
исключения, созданные в блоке finally подавляют исключение, созданное ранее в блоке try или catch.
Java 7 пример:http://ideone.com/0YdeZo
С документация по пример:
static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { if (br != null) br.close(); } }
однако, в этом примере, если методы readLine и close оба броска исключения, то метод readFirstLineFromFileWithFinallyblock создает исключение, созданное из блока finally; исключение выброшенный из блока try подавляется.
новая
try-with
синтаксис Java 7 добавляет еще один шаг подавления исключений: исключения, брошенные в блоке try, подавляют те, которые были брошены ранее в части try-with.из того же примера:
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()); } }
исключение может быть выброшено из блока кода, связанного с попробовать-оператор с ресурсами. В приведенном выше примере, исключение может быть выброшены из блока try, и до двух исключения могут быть брошены из инструкции try-with-resources при попытке закрыть Объекты ZipFile и BufferedWriter. Если исключение выбрасывается из попробуйте блок и одно или несколько исключений выбрасываются из оператор try-with-resources, затем эти исключения, вызванные из оператор try-with-resources подавляется, и возникает исключение по блоку-это тот, который бросает writeToFileZipFileContents метод. Вы можете получить эти подавленные исключения позвонив по перекидным.getSuppressed метод из исключение в блоке try.
в коде из вопроса каждый блок явно отбрасывает старое исключение, даже не регистрируя его, не очень хорошо, когда вы пытаетесь решить некоторые ошибки:
С
throw new Exception("2");
выдаетcatch
иtry
, это не будет пойман снова.
посмотреть 14.20.2. Выполнение попробовать-наконец-то и попробовать-поймать-наконец-то.вот что происходит:
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 }
Ваш вопрос очень очевиден, и ответ прост в той же степени.. объект исключения с сообщением как " 2 "перезаписывается объектом исключения с сообщением как" 3".
объяснение : Когда возникает исключение, его объект он бросил, чтобы поймать блок для обработки. Но когда исключение происходит в самом блоке catch, его объект передается во внешний блок CATCH (если таковой имеется) для обработки исключений. И то же самое произошло здесь. Этот Объект исключения с сообщением " 2 " передается во внешний блок catch . но ждать.. Перед выходом из внутреннего блока try-catch он должен выполнить окончательно. Здесь произошло изменение, о котором мы беспокоимся. Выбрасывается новый объект исключения (с сообщением "3") или этот последний блок, который заменил уже брошенный объект исключения(с сообщением"2"). в результате чего , когда выводится сообщение объекта исключения, мы получаем переопределенное значение т. е." 3", а не"2".
сохранить Помните:только один объект исключения может быть обработан блоком CATCH.
The
finally
блок всегда работает. Либо тыreturn
изнутри блока try или создается исключение. Исключение, брошенное вfinally
блок переопределит тот, который был брошен в ветке catch.кроме того, выбрасывание исключения не вызовет никаких выходных данных само по себе. Линия
throw new Exception("2");
ничего не будет выписывать.
согласно вашему коду:
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()); }
как вы можете увидеть здесь:
- print A и выбрасывает исключение
# 1
;- это исключение было поймано оператором catch и print
B - # 2
;- блок наконец-то
# 3
выполняет после try-catch (или только try, если не произошло никакого исключения) заявление и печатаетC - # 4
и выбрасывается новое исключение;- этот поймал внешний оператор catch
# 5
;результат
ABC3
. И2
опускается так же, как и1