У меня есть небольшая теоретическая проблема с конструкциями 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")?
print(e.getMessage())
. Вы думали, что результат будетAB2C3
: вы думали, что самый внешнийcatch
блок будет выполнен дважды?Ответы:
Из спецификации языка Java 14.20.2. :
Итак, когда есть блок catch, который выдает исключение:
но есть также блок finally, который также генерирует исключение:
Exception("2")
будут отброшены и толькоException("3")
будут распространены.источник
return
заявлений. Если ваш блок finally имеет возврат, он переопределит любой возврат в блокеtry
илиcatch
. Из-за этих «особенностей» хорошей практикой является то, что блок finally никогда не должен выдавать исключение или иметь оператор return.Исключения, сгенерированные в блоке finally, подавляют исключение, сгенерированное ранее в блоке try или catch.
Пример Java 7: http://ideone.com/0YdeZo
Из примера Javadoc :
Новый
try-with
синтаксис Java 7 добавляет еще один шаг подавления исключений: исключения, сгенерированные в блоке try, подавляют те, что были сгенерированы ранее в части try-with.из того же примера:
В коде из вопроса каждый блок явно отбрасывает старое исключение, даже не регистрируя его, не очень хорошо, когда вы пытаетесь устранить некоторые ошибки:
http://en.wikipedia.org/wiki/Error_hiding
источник
Так
throw new Exception("2");
как выброшен изcatch
блока и нетtry
, он не будет пойман снова.Смотри 14.20.2. Выполнение try-finally и try-catch-finally .
Вот что происходит:
источник
Ваш Вопрос очень очевиден, и ответ в той же степени прост. Объект Exception с сообщением как «2» перезаписывается объектом Exception с сообщением как «3».
Объяснение: Когда возникает исключение, его объект выбрасывается, чтобы перехватить блок для обработки. Но когда исключение возникает в самом блоке catch, его объект передается в блок OUTER CATCH (если есть) для обработки исключений. И то же самое произошло здесь. Объект исключения с сообщением «2» передается в блок захвата OUTER. Но подождите .. Прежде чем покинуть внутренний блок try-catch, он ДОЛЖЕН ИСПОЛЬЗОВАТЬСЯ ОКОНЧАТЕЛЬНО. Здесь произошли перемены, которые нас беспокоят. Новый объект EXCEPTION (с сообщением «3») выбрасывается или этот блок finally заменяет уже брошенный объект Exception (с сообщением «2»), в результате чего при выводе сообщения объекта Exception получается переопределенное значение, т. е. «3», а не «2».
Помните: только один объект исключения может быть обработан в блоке CATCH.
источник
finally
Блок всегда работает. Либо выreturn
из блока try, либо выдается исключение. Исключение, сгенерированное вfinally
блоке, переопределит одно, сгенерированное в ветви catch.Кроме того, выбрасывание исключения не приведет к самому выводу. Линия
throw new Exception("2");
ничего не напишет.источник
Согласно вашему коду:
Как вы можете видеть здесь:
# 1
;B - # 2
;# 3
выполняется после оператора try-catch (или только try, если не было ни одного исключения) и печатаетC - # 4
и выдает новое исключение;# 5
;Результат есть
ABC3
. И2
опускается так же, как1
источник