Кто-либо может сказать мне, почему вывод этого класса является 'xa'?
почему другое исключение (RuntimeException и Исключение) не будет поймано?
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");}
}
}
Единственное исключение, которое выбрасывается, это то, которое находится прямо рядом с оператором throw. Другое исключение создается, но не выбрасывается. Невозможно бросить два исключения одновременно.
Обычно, когда исключение передается в конструктор другого исключения, это указывает на то, что то исключение является причиной этого. Однако на самом деле выбрасывается только то исключение, которое находится рядом с оператором throw.
В этом случае NullPointerException не поддерживает исключение в своем конструкторе, потому что оно не вызвано другими исключениями, оно вызвано нулевыми ссылками. В других случаях это связано с тем, что цепочка исключений не была введена в Java до версии 1.4, поэтому некоторые устаревшие классы исключений не были оснащены новыми конструкторами. В этом случае вы можете использовать метод initCause(Throwable)
, чтобы сделать то, что должен был сделать конструктор.
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!!"
}
поймать
вещи, выброшенные из того места, где ваша попытка
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!
x
печатается первым блоком catch
(исключение NullPointerException
).
a
печатается блоком finally
.
Блок finally
выполняется всегда, независимо от того, было сгенерировано исключение или нет.
РЕДАКТИРОВАТЬ:
Будет выполнен только один блок catch
. В вашем случае, поскольку NullPointerException
extends RuntimeException
extends Exception
, первый блок catch
, который принимает эти исключения, будет обрабатывать исключение.
Замечание: обычно вы не должны обнаруживать NullPointerException
. См. Это учебное пособие на веб-сайте Sun.
Здесь вы бросаете исключение NullPointerException в блоке try, и поэтому оно будет перехвачено в первом применяемом блоке catch. Как только он пойман, он пойман.
Java обрабатывает исключение с помощью первого блока catch, который соответствует выброшенному исключению. Так как брошенное исключение - это NullPointerException
, оно перехватывается первым блоком catch, а остальные игнорируются. Блок finally
всегда выполняется (если только вы не завершаете работу аномально, например, System.exit).
Таким образом, вы получаете вывод "x" из блока отлова NullPointerException, а "a" выводится из блока finally.
Принцип работы try/catch следующий:
Потому что вы бросаете только одно исключение. Вы можете создавать исключения сколько угодно, но пока вы их не бросите, они никогда не будут пойманы. Вы никогда не бросаете общее исключение Exception, поэтому оно никогда не может быть поймано.
И кстати, не существует способа бросить два исключения одновременно. Если вы напишете:
try
{
throw new Exception();
throw new NullPointerException();
}
catch (NullPointerException e)
{
System.out.printlne("first");
}
catch (Exception e)
{
System.ot.println("second");
}
Компилятор просто выкинет вас, потому что второй бросок - это недостижимый код. Исключение - это как GOTO.
Возникла исключительная ситуация NullPointerException, которая была обработана и напечатана в консоли.
Затем выполняется оператор finally и выводится «a» на консоль, и, следовательно, вы получаете «xa».
Будет выполнен только первый блок catch, соответствующий типу брошенного исключения. Поэтому, даже если NullPointerException
является RuntimeException
и Exception
, оно уже было поймано до этих блоков.
Если вы измените порядок блоков catch, то будет выполнен блок Exception
. (Однако это не рекомендуется. Всегда следует располагать блоки catch в порядке от наиболее специфичного к наименее специфичному, как в примере)