Подтвердить что ты не робот

Почему не catching Exception catch RuntimeException?

Это очень странно для меня. 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), который, я считаю, является синтаксической ошибкой из-за наследования?

4b9b3361

Ответ 1

Предпосылка вопроса ошибочна, потому что ловить Exception ловить RuntimeException. Демо-код:

public class Test {
    public static void main(String[] args) {
        try {
            throw new RuntimeException("Bang");
        } catch (Exception e) {
            System.out.println("I caught: " + e);
        }
    }
}

Вывод:

I caught: java.lang.RuntimeException: Bang

У вашего цикла будут проблемы, если:

  • callbacks имеет значение null
  • что-либо изменяет callbacks во время выполнения цикла (если это была коллекция, а не массив)

Возможно, это то, что вы видите?

Ответ 2

catch (Exception ex) { ... }

WILL catch RuntimeException.

Все, что вы помещаете в блок catch, будет уловлено, а также подклассы.

Ответ 3

Ловля Exception поймает RuntimeException

Ответ 4

Я столкнулся с похожим сценарием. Это происходило потому, что инициализация classA зависела от инициализации класса B. Когда статический блок класса B столкнулся с исключением среды выполнения, класс B не был инициализирован. Из-за этого классB не выдал никакого исключения, и инициализация classA также не удалась.

class A{//this class will never be initialized because class B won't intialize
  static{
    try{
      classB.someStaticMethod();
    }catch(Exception e){
      sysout("This comment will never be printed");
    }
 }
}

class B{//this class will never be initialized
 static{
    int i = 1/0;//throw run time exception 
 }

 public static void someStaticMethod(){}
}

И да... catching Exception также поймает исключения времени выполнения.