Комментарии 19
У меня из этой заметки вывод один. Впрочем, ничего нового для себя.
+15
надо быть проще… куча вложенных try...catch это не хорошо и сильно усложняет отладку
-6
НЛО прилетело и опубликовало эту надпись здесь
Не хватает тега «ruby» :)
-10
4+E1
А почему этот кусок должен был выполниться? Внешний try никаких исключений не выбрасывает,
throw new Exception("E1")
это исключение считается отловленным, раз есть блок finally. Серьезно, я не совсем понимаю, какого поведения вы ждали
0
Суть блока
Код в блоке
В строке 4 выкидывается исключение
В блоке
Теперь у нас остаётся одно необработанное исключение
В самом конце на строке 17 выводится «5».
В результате же описанного бага, исключение
finally
в том, что он выполняется в любом случае, было ли выброшено исключение или нет. Исключения он не обрабатывает!Код в блоке
try
выполняется до места выброса исключения E1
, то есть, до строки 4 в примере. Выводится «1».В строке 4 выкидывается исключение
E1
и далее оно ловится в блоке catch
, если таковой присутствует. В данном случае блока catch
нет, поэтому исключение пробрасывается выше. Однако, есть блок finally
, который выполняется в любом случае.В блоке
finally
содержится свой блок с try...catch
, он и начинает выполняться. Внутри блока try
на строке 7 выводится «2», затем на строке 8 бросается исключение E2
(это уже второе по счёту исключение, предыдущее выброшенное исключение ещё никто не обработал!), которое тут же ловится соответствующим блоком catch
на строке 9, в котором выводится «3» (на строке 10). До строчки с выводом «4-» (строка 13) управление не дойдёт никогда.Теперь у нас остаётся одно необработанное исключение
E1
, выброшенное на строке 4. Поскольку вся эта конструкция с блоком try...finally
завёрнута ещё в один блок try...catch
, ловящий исключения нужного типа, исключение должно быть поймано на строке 14 и обработано на строке 15. В результате вывод дополнится «4+E1».В самом конце на строке 17 выводится «5».
В результате же описанного бага, исключение
E1
просто забывается, соответственно, внешний блок try...catch
его не ловит.+1
Исключения он не обрабатывает!
Я ж не говорю, что она их именно обрабатывает. Исключение считается обработанным.
Считайте, что
try{
...
} finally {
..
}
это просто сокращенная запись
try{
...
} catch(Exception$e) {
//do nothing
} finally {
..
}
В данном случае блока catch нет, поэтому исключение пробрасывается выше
Когда блока catch нет, то выскакивает ошибка. Что наводит на мысль, что неявно он там есть.
-2
Эм. Почему он там есть? Если нет блока
catch
, то исключение не перехватывается, не обрабатывается и, разумеется, будет ошибка (не перехваченного исключения). Или вы о какой-то другой ошибке? И почему вы решили, что?try{ ... } finally { .. }
это просто сокращенная запись
try{ ... } catch(Exception$e) { //do nothing } finally { .. }
0
С finally в случае исключения условно говоря вызывается вирутальная процедура, тело которой записано в блоке finally, а после этого исключение, котрое как было, так и осталось, забрасывается выше. В случае с catch перед тем как вызывать виртуальную процедуру в блоке catch, исключение удаляется из цепочки. В компилируемых языках так, наверняка, здесь аналогично.
0
промазал
0
НЛО прилетело и опубликовало эту надпись здесь
Думаю про такой код тоже самое нельзя сказать:
А если нет разницы, зачем писать больше? :) (результат выполнения тут)
Так же думаю что описание к try/catch/finally несколько устарело и не отражает действительности раз пример в самой заметке работает и никто ранее не удивился отсутствия catch.
Опять же само по себе try-finally без catch имеет под собой смысл когда вне зависимости от тог будет брошен в try исключение или нет необходимо выполнить действие, а само исключение ловится где-то по стеку выше.
try {
try {
echo "1\n";
throw new Exception("E1");
} catch (Exception $e) {
throw $e;
} finally {
try {
echo "2\n";
throw new Exception("E2");
} catch (\Exception $e) {
echo "3\n";
}
}
echo "4-\n";
} catch (\Exception $e) {
echo "4+".$e->getMessage()."\n";
}
echo "5\n";
А если нет разницы, зачем писать больше? :) (результат выполнения тут)
Так же думаю что описание к try/catch/finally несколько устарело и не отражает действительности раз пример в самой заметке работает и никто ранее не удивился отсутствия catch.
Опять же само по себе try-finally без catch имеет под собой смысл когда вне зависимости от тог будет брошен в try исключение или нет необходимо выполнить действие, а само исключение ловится где-то по стеку выше.
+1
НЛО прилетело и опубликовало эту надпись здесь
Проблема именно в finally. В примерах выше видно что в зависимости от версии мы получаем на выходе различный вариант. В документации лишь необходимо поправить что try должен иметь либо хотя бы один блок независимо от того finally или catch. Опять же поведение интерпретатора относительно finally согласуется с поведением finally в Java что тоже на мой взгляд хорошо. У php, конечно, свой путь, но некоторым базовым структурам лучше бы быть унифицированнее.
+1
Проверил на JPHP, выводит 1 2 3 4+E1 5 как и в PHP 5.6
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Опасный finally или ждем 5.6