Это очень странно для меня. RuntimeException
наследует от Exception
, который наследует от Throwable
.
catch(Exception exc) { /* won't catch RuntimeException */
но
catch(Throwable exc) { /* will catch RuntimeException */
Я знаю, что RuntimeException
особенность в том, что он не установлен. Но, насколько я понимаю, это касается только того, нужно ли объявлять исключения, а не быть ли они пойманы. И даже тогда я не знаю, почему эта логика сломалась бы на ловле Throwable.
Это очень актуально для меня, так как у меня есть ситуация, когда RuntimeExceptions могут быть выбраны в терминальной операции. Я не уверен имя этого шаблона, но что-то вроде этого, мой класс EmailRoller
принимает массив Callbacks
. Код выглядит следующим образом:
for(Callback cb : callbacks) {
try {
cb.call(item);
}
catch(Exception exc) {
logger.error("Error in callback: ", exc);
}
}
Итак, это случай, когда что-то вроде OOME нужно пролететь, потому что, если один из этих обратных вызовов потребляет всю память машины, это точно, так как heck будет влиять на работу других. Но a NullPointerException
? Или IndexOutOfBoundsException
? Это повлияет на обратный вызов, но не будет препятствовать запуску других.
Кроме того, это немного корпоративный дизайн. Различные программисты или команды могут добавлять обратные вызовы для обработки элемента, но они должны быть изолированы друг от друга. Это означает, что программист, ответственный за изоляцию этих обратных вызовов друг от друга, не должен полагаться на них, чтобы убедиться, что ошибки не проскальзывают. Захват Exception
должен быть о правильной строке, но это происходит не потому, что проскальзывает RuntimeException
. Поэтому мой более общий вопрос: какой хороший образец здесь? Просто catch(Exception | RuntimeException exc)
, который, я считаю, является синтаксической ошибкой из-за наследования?