Исключение 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