Неопределенность в том, где ловится исключение - PullRequest
1 голос
/ 02 мая 2011

В приведенном ниже коде, где будет поймано выброшенное исключение?

public interface MyInterface {
    public void execute() throws Exception;
}

public class MyImplementor implements MyInterface {
    public void execute() throws Exception {
        throw new MyException();
    }
}

public class MyMainClass {
    public static void main(String args[]) {
        try {
            MyImplementor temp = new MyImplementor();
            temp.execute();
        } catch(MyException e) {
            sysout("MyException");
        } catch(Exception e) {
            sysout("Exception");
        }
    }
}

(MyException - расширение класса Exception)

Так, где ловится это исключение? Кроме того, какова логика, используемая компилятором, чтобы решить, где он пойман?

Если бы я поместил

catch(Exception e)

до

catch(IOException e)

это изменит поток управления?

Ответы [ 5 ]

5 голосов
/ 02 мая 2011

Так, где ловится это исключение?

В первом обработчике.

Кроме того, какова логика, используемая компилятором, чтобы решить, где он пойман?

Это не компилятор, который "решает" ...

Поведение определяется спецификацией языка Java раздел 11.3 :

"Когда генерируется исключение, управление передается из кода, вызвавшего исключение, в ближайший динамически заключающий в себя оператор catch оператора try (§14.20) , который обрабатывает исключение".

(выделение добавлено).

Другими словами, распространяющееся исключение сравнивается (используя эквивалент instanceof) с типом исключения каждого из обработчиков, в объявленном порядке обработчиков . Первый, соответствующий исключению, выполняется.

Если бы я поместил "catch(Exception e)" перед "catch(IOException e)", это изменило бы поток управления?

Да. (Предполагая, что вы имели в виду MyException, а не IOException.) Это прямое логическое следствие поведения, описанного выше.


Это означает, что вы должны сначала заказать обработчики с обработчиками для самых конкретных исключений. Некоторые Java-компиляторы и инструменты для определения качества кода / ошибок предупреждают вас, если вы ошиблись, но это не ошибка компиляции.

3 голосов
/ 02 мая 2011

Это что-то вроде if...else if. Если выполнено одно условие, оно выйдет из оставшихся условий ... В случае исключений catch(Exception e) удовлетворяет всем видам исключений, так как является родителем всех исключений. , Так что исключение ловится на самом верхнем уровне. Компилятор не допустит этого. Так что ставьте catch в соответствии с порядком наследования от снизу вверх . Только тогда вы можете получить исключение в соответствии с его типом.

2 голосов
/ 02 мая 2011

ты не можешь этого сделать. Последовательность (проверенных) исключений соответствует последовательности наследования. Вы не можете добавить родительское исключение перед исключением, которое унаследовано от этого родителя. IDE жалуется, и код не будет скомпилирован!

В вашем случае, если ваш код выдает IOException, он будет перехвачен в блоке перехвата IOException, прежде чем он достигнет блока перехвата Exception. В других случаях блок Exception- catch будет перехватывать любые другие исключения

1 голос
/ 02 мая 2011

В вашем коде MyException не определено, но оно должно расширять Exception или RuntimeException. В любом случае это ничего не изменит, ваша программа выведет «MyException», так как это тип создаваемого исключения.

1 голос
/ 02 мая 2011

а) вы не можете изменить порядок блоков захвата.Если бы вы это сделали, блок для IOException стал бы недоступным - экземпляр IOException также является экземпляром Exception, поэтому блок catch (Exception e) перехватит его, и вы никогда не нажмете на блок catch (IOException e).В этом случае код не будет компилироваться - недоступный код не разрешен.

b) поскольку MyException расширяет Exception, а не IOException, он никогда не будет перехвачен блоком catch (IOException e).Поэтому он будет перехвачен блоком catch (Exception e).

ОБНОВЛЕНИЕ

Вы изменили вопрос, поэтому ответ немного отличается:

a) Вы по-прежнемуне может перевернуть блоки.

b) Теперь, когда вы изменили первый блок на catch (MyException e), выброшенное исключение будет поймано там.Процедура заключается в том, что компилятор просматривает каждый блок catch.Если исключение, которое оно пытается обработать, является экземпляром перехваченного исключения, выполняется этот блок catch.Если нет, он переходит к следующему блоку перехвата.Если блоков перехвата больше нет, выполнение резко прерывается (термин из спецификации языка Java).

...