На вопрос о Java в университете был приведен фрагмент кода:
class MyExc1 extends Exception {}
class MyExc2 extends Exception {}
class MyExc3 extends MyExc2 {}
public class C1 {
public static void main(String[] args) throws Exception {
try {
System.out.print(1);
q();
}
catch (Exception i) {
throw new MyExc2();
}
finally {
System.out.print(2);
throw new MyExc1();
}
}
static void q() throws Exception {
try {
throw new MyExc1();
}
catch (Exception y) {
}
finally {
System.out.print(3);
throw new Exception();
}
}
}
Меня попросили дать свой вывод. Я ответил13Exception in thread main MyExc2
, но правильный ответ 132Exception in thread main MyExc1
. Почему это так? Я просто не могу понять, куда MyExc2
идет.
Вот что говорит Википедия об окончательном предложении:
Давайте рассмотрим вашу программу.
Итак,
1
будет выводиться на экран, затемq()
вызывается. Вq()
, исключение выдается. Затем исключение отлавливается,Exception y
но ничего не делает. Наконец пункт затем выполняется (он должен), а значит,3
будет выведено на экран. Поскольку (в методеq()
есть исключение, которое выдается в предложении finally ,q()
метод также передает исключение в родительский стек (согласноthrows Exception
объявлению метода),new Exception()
который будет выброшен и перехваченcatch ( Exception i )
,MyExc2
будет выдано исключение (сейчас добавьте его в стек исключений). ), но, наконец, вmain
блоке будет выполняться первым.Так что в
, Наконец , статья называется ... (помните, мы просто поймали
Exception i
и бросилиMyExc2
) , в сущности,2
печатаются на экране ... и после того , как2
будет напечатан на экране,MyExc1
исключение.MyExc1
обрабатываетсяpublic static void main(...)
методом.Вывод:
Лектор правильный! :-)
По сути , если у вас есть предложение finally в предложении try / catch, будет выполнено поле finally ( после перехвата исключения перед выбрасыванием перехваченного исключения)
источник
catch
Выполняется такq()
кинулException
из своегоfinally
блока.q
передает выполнение в пустойcatch
блок вq
(который поглощает это исключение), затем вfinally
блок вq
. В конце концов, блок печатает3
, затем выдает новое исключение, которое благодаряq
sthrows Exception
передается по стеку родителю.Исключения в блоке finally заменяют исключения в блоке catch.
Цитирование из издания 14 спецификации языка Java :
источник
Предложение finally выполняется, даже когда исключение генерируется из любого места в блоке try / catch.
Потому что это последнее, что будет выполнено в
main
и выдает исключение, это исключение, которое видят вызывающие.Следовательно, важно убедиться, что в
finally
предложении ничего не выдается, поскольку оно может проглотить исключения изtry
блока.источник
Не
method
можетthrow
два исключения одновременно. Он всегда будет бросать последний бросокexception
, который в этом случае всегда будет одним изfinally
блока.Когда
q()
выбрасывается первое исключение из метода , оно будет перехвачено, а затем проглочено исключением, вызванным блоком finally.q () -> Брошенный
new Exception
->main
catch Exception
->throw
new Exception
->finally
бросить новыйexception
(и тот, который изcatch
"потерян")источник
Самый простой способ думать об этом - представить, что существует глобальная переменная для всего приложения, которая содержит текущее исключение.
Поскольку каждое исключение выдается, "currentException" устанавливается в это исключение. Когда приложение заканчивается, если currentException равно! = Null, тогда среда выполнения сообщает об ошибке.
Кроме того, блоки finally всегда запускаются до выхода из метода. Затем вы можете запросить фрагмент кода для:
Порядок, в котором выполняется приложение:
источник
Общеизвестно, что блок finally выполняется после try и catch и всегда выполняется .... Но, как вы видели, иногда немного сложно проверить этот фрагмент кода ниже, и вы увидите, что операторы return и throw не используют не всегда делать то, что они должны делать в том порядке, в котором мы ожидаем тему.
Приветствия.
источник
Порядок:
https://www.compilejava.net/
источник
Логика ясна до завершения печати
13
. Тогда исключение брошено вq()
пойманаcatch (Exception i)
вmain()
иnew MyEx2()
готов бросить. Однако, прежде чемfinally
вызвать исключение, блок должен быть выполнен первым. Затем вывод становится132
иfinally
просит выдать еще одно исключениеnew MyEx1()
.Поскольку метод не может выдать больше одного
Exception
, он всегда выбрасывает последнееException
. Другими словами, если оба блокаcatch
иfinally
блок пытаются выполнить бросокException
, тоException
входящие данные будут проглочены, и будет выдано только исключениеfinally
.Таким образом, в этой программе исключение
MyEx2
проглатывается иMyEx1
выбрасывается. Это исключение выбрасываетсяmain()
и больше не перехватывается, поэтому JVM останавливается и конечный результат -132Exception in thread main MyExc1
.По сути, если у вас есть предложение
finally
intry/catch
, afinally
будет выполняться ПОСЛЕ перехвата исключения , но ДО создания любого перехваченного исключения , и ТОЛЬКО самое последнее исключение будет выброшено в конце .источник
Я думаю, вам просто нужно пройтись по
finally
блокам:finally
вq
печати "3".finally
вmain
печати "2".источник
Чтобы справиться с такой ситуацией, то есть обработать исключение, вызванное блоком finally. Вы можете окружить блок finally блоком try: Посмотрите на приведенный ниже пример в python:
источник
Я думаю, что это решит проблему:
источник