Почему я не могу поймать исключение более одного раза?

1

JLS 8, 14.20:

Оператор try выполняет блок. Если значение выбрано, и оператор try имеет одно или несколько кластеров catch, которые могут его поймать, тогда управление будет передано в первое предложение catch.

Похоже, у меня могут быть, например, два предложения catch для одного и того же типа исключения. Но когда я попробую это, я получу ошибку времени компиляции.

public static void main (String[] args) throws java.lang.Exception
{
    try{
    } catch(RuntimeException ioe){
    } catch(NumberFormatException e){ //Already caught
    } 
}

IDEONE

Не могли бы вы объяснить это с помощью JLS?

  • 0
    У вас может быть два, но It is a compile-time error if a union of types contains two alternatives Di and Dj (i ≠ j) where Di is a subtype of Dj (§4.10.2). , Если вам нужно, поместите try-catch (NFE) и перебросьте его, а вокруг этого поставьте try-catch (RE)
  • 0
    Какой смысл перехватывать одно и то же исключение более одного раза в одном и том же операторе try? Ошибка компиляции довольно ясна в этом unreachable catch block ...
Показать ещё 4 комментария
Теги:
exception
language-lawyer

4 ответа

2
Лучший ответ

NumberFormatException - это специализация RuntimeException, поэтому ваше исключение NumberFormatException будет уже захвачено первым оператором. Однако вы можете переключить порядок этих двух предложений catch; но имейте в виду, что только один будет выполнен:

  • предложение NumberFormatException, если это исключение имеет этот тип
  • предложение RuntimeException для всех других типов RuntimeException

Что касается того, почему именно так... Ну вот как был разработан язык. Если бы все соответствующие блоки блокировки выполнялись, было бы труднее обрабатывать ошибки правильно.

  • 0
    Так вот, как был разработан язык. Не могли бы вы привести цитату, которую он доказывает? Дизайн языка должен быть полностью описан в спецификации, верно?
  • 0
    Часть спецификации, которую вы цитировали в своем вопросе, точно говорит об этом: выполняется первое предложение catch, соответствующее исключению, что означает, что выполняется только одно соответствующее предложение catch. Что касается спецификации, которая говорит, почему вы не можете писать предложения catch в порядке, показанном в вашем вопросе, это другой вопрос (возможно, написанный где-то еще)
Показать ещё 2 комментария
1

NumberFormatException - это подтип RuntimeException Когда вы поймали RuntimeException, он поймает все типы RuntimeException включая NumberFormatException. Вот почему он говорит, что уже пойман.

1

Ошибка компилятора вы получаете результаты из иерархии исключенных исключений.

NumberFormatException extends IllegalArgumentException extends RuntimeException

Подумайте о блоке захвата в качестве систем безопасности. Сеть NumberFormatException довольно мала, так как это особый случай высших исключений иерархии. Сеть RuntimeException является одной из самых больших и будет захватывать что-либо на этом уровне (кроме Exception и Throwables, которые являются "превосходящими"). То, что вы сделали, это разместить небольшую сеть ниже большой сети. Поэтому компилятор достаточно вежлив, чтобы дать вам подсказку о том, что меньшая сеть никогда не будет достигнута.

(Я знаю, что метафар не на 100% точнее, но в этом контексте отлично работает.)

Если вы сначала поймаете NumberFormatException, а затем RuntimeException, компилятор с радостью согласится! :-) Вы также можете перебросить пойманное исключение из первого блока.

1

Поскольку RunTimeException является базовым классом NumberFormatException. http://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html

  • 0
    Да, я знаю. Я спрашиваю, почему мы не можем поймать одно и то же исключение два или более раз?
  • 0
    Это потому, что в спецификации указано «первое» предложение catch.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню