Вопрос о множественном «улове» - PullRequest
9 голосов
/ 07 мая 2010

Может кто-нибудь сказать мне, почему выходные данные этого класса 'xa'?

, почему другое исключение (RuntimeException и Exception) не будет перехвачено?

public class Tree {
    public static void main(String... args) {
        try
        {
            throw new NullPointerException(new Exception().toString());
        }
        catch (NullPointerException e)
        {
            System.out.print("x");
        }
        catch (RuntimeException e)
        {
            System.out.print("y");
        }
        catch (Exception e)
        {
            System.out.print("z");   
        }        
        finally{System.out.println("a");}
    }
}

Ответы [ 9 ]

16 голосов
/ 07 мая 2010

То, что создано исключение, не означает, что оно выброшено

public static void main(String[] args) {
    new Exception();
    System.out.println("Yippee!!");
    // prints "Yippee!!"
}

То, что есть предложение catch, не означает, что что-то было перехвачено

public static void main(String[] args) throws Exception {
    try {
        System.out.println("No math for me!");
    } catch (ArithmeticException e) {
        System.out.println("Math was wronged!");
    } // prints "No math for me!"
}

Исключение может быть выброшено при создании другого исключения

public static void main(String[] args) {
    try {
        throw new NullPointerException(args[-1]);
    } catch (NullPointerException e) {
        System.out.println("Ooops!");
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Ooh lala!!");           
    } // prints "Ooh lala!!"
}

Вы можете только catch вещи, выброшенные из того места, где находится try

public static void main(String[] args) throws Exception {
    try {
        args[-1] = null;
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Gotcha!");
        args[1/0] = null;
    } catch (ArithmeticException e) {           
        System.out.println("You missed me!");
    } // prints "Gotcha!"
} // Exception in thread "main" java.lang.ArithmeticException: / by zero

Практически при "всех" обстоятельствах,finally всегда выполняется

public static void main(String[] args) {
    try {
        throw new Exception();
    } catch (Exception e) {
        System.out.println("Oops!");
        args[-1] = null;
    } finally {
        System.out.println("Yay!");
    } // prints "Oops!", "Yay!",
} // Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1

Резкое завершение finally превосходит внезапное завершение try/catch

static String greetings() {
    try {
        return "No mood!";
    } finally {
        return "Hey buddy!";
    }
}   
public static void main(String[] args) throws Exception {
    System.out.println(greetings()); // prints "Hey buddy!"
    try {
        args[-1] = null;
    } catch (ArrayIndexOutOfBoundsException e) {
        throw new Exception("Catch me if you can!");
    } finally {
        throw new Exception("Yoink!");
    }
} // Exception in thread "main" java.lang.Exception: Yoink!
12 голосов
/ 07 мая 2010

Единственное выбрасываемое исключение - это одно рядом с оператором throw. Другой создан, но не брошен. Невозможно выдать два исключения одновременно.

Обычно, когда исключение передается в конструкторе другого исключения, это означает, что причиной является это исключение. Однако единственное исключение, которое на самом деле выдается, это исключение рядом с оператором throw.

В этом случае NullPointerException не поддерживает исключение в своем конструкторе, поскольку оно не вызвано другими исключениями, а вызвано нулевыми ссылками. В других случаях это происходит из-за того, что цепочка исключений не была введена в Java до версии 1.4, поэтому некоторые устаревшие классы исключений не были обновлены новыми конструкторами. В этом случае вы можете использовать метод initCause(Throwable), чтобы сделать то, что сделал бы конструктор.

7 голосов
/ 07 мая 2010

x печатается первым блоком catch (NullPointerException).

a печатается блоком finally.

Блок finally всегда выполняется независимо от того, было сгенерировано исключение или нет.

EDIT:

Будет выполнен только один catch блок. В вашем случае, поскольку NullPointerException extends RuntimeException extends Exception, первый блок catch, который принимает эти исключения, будет обрабатывать исключение.

Примечание: обычно вы не должны ловить NullPointerException. См. учебник с веб-сайта Sun.

6 голосов
/ 07 мая 2010

Будет выполнен только первый блок перехвата, который соответствует выброшенному типу исключения. Таким образом, хотя NullPointerException является RuntimeException и Exception, оно уже было обнаружено до этих блоков.

Если вы измените порядок блоков перехвата, будет выполнен блок Exception. (Однако это не рекомендуется. Вы должны всегда размещать свои блоки catch в порядке от наиболее специфического до наименее специфического, как в примере.)

3 голосов
/ 07 мая 2010

Здесь вы генерируете исключение NullPointerException в блоке try, и он будет перехвачен в первом применяемом блоке catch.Как только он пойман, он пойман.

2 голосов
/ 07 мая 2010

Java обрабатывает исключение с помощью блока first , который соответствует выброшенному исключению.Поэтому, поскольку выбрасывается исключение NullPointerException, оно перехватывается первым блоком перехвата, а остальные игнорируются.Блок finally всегда выполняется (если вы не завершили ненормально, например, System.exit).

Таким образом, вы получаете вывод «x» из блока перехвата NullPointerException, а «a» выводится из блока finally.

0 голосов
/ 07 мая 2010

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

И, кстати, нет никакого способа выдать два исключения одновременно. Если вы напишите:

try
{
    throw new Exception();
    throw new NullPointerException();
}
catch (NullPointerException e)
{
  System.out.printlne("first");
}
catch (Exception e)
{
  System.ot.println("second");
}

Компилятор просто выгонит вас, потому что второй бросок - недоступный код. Исключение похоже на GOTO.

0 голосов
/ 07 мая 2010

Способ пробовать / ловить работает следующим образом:

  1. Код тела выполняется до конца или до появления исключения;
  2. Если выброшено исключение и имеется совпадающий перехват, выполняется код для соответствующего предложения перехвата;
  3. Код finally всегда выполняется независимо от того, было ли выброшено исключение и было ли оно перехвачено
0 голосов
/ 07 мая 2010

Было сгенерировано исключение NullPointerException, оно было обработано и напечатано на консоли в виде буквы "x".

Затем выполняется оператор finally, который выводит «a» на консоль, и поэтому вы получаете «xa».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...