Question about multiple 'catch'
Can anyone tell me why the output of this class is 'xa'?
why the other exception(RuntimeException and Exception ) won't be caught?
public class Tree {
public static void main(String... args) {
try
{
throw new NullPointerException(new Exception().toString());
开发者_Python百科 }
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");}
}
}
Just because an exception is created, doesn't mean it's thrown
public static void main(String[] args) {
new Exception();
System.out.println("Yippee!!");
// prints "Yippee!!"
}
Just because there's a catch
clause, doesn't mean something was caught
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!"
}
Exception can be thrown during the creation of another exception
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!!"
}
You can only catch
things thrown from where your try
is
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
Practically under "all" circumstances, finally
is always executed
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
Abrupt completion of finally
trumps abrupt completion of 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!
The only exception thrown is the one right next to the throw statement. The other is created but not thrown. It is not possible to throw two exceptions simultaneously.
Typically when an exception is passed in the constructor of another exception it is to indicate that the that exception is the cause of this one. However, the only exception actually being thrown is the one next to the throw statement.
In this case NullPointerException does not support an Exception in its constructor because it is not caused by other exceptions, it is caused by null references. In other cases it is because exception chaining was not introduced in Java until 1.4, so some legacy exception classes didn't get retro-fitted with new constructors. In that case you can use the initCause(Throwable)
method to do what the constructor would have done.
The x
is printed by the first catch
block (the NullPointerException
).
The a
is printed by the finally
block.
The finally
block is always executed whether there was exception thrown or not.
EDIT:
Only one catch
block will be executed. In your case, since NullPointerException
extends RuntimeException
extends Exception
, the first catch
block that accepts these Exceptions will handle the exception.
On a side note: You normally shouldn't be catching a NullPointerException
. See this tutorial from the Sun website.
Only the first catch block that matches the type of exception thrown will be executed. So even though NullPointerException
is a RuntimeException
and an Exception
, it has already been caught before those blocks.
If you reverse the order of the catch blocks, then the Exception
block will execute. (This is not recommended, though. You should always put your catch blocks in the order of most specific to least specific, as you have in the example.)
Here, you throw a NullPointerException in the try block, and so it will be caught in the first catch block that applies. Once it's caught, it's caught.
Java handles an Exception with the first catch block that matches the Exception thrown. So since the exception thrown is a NullPointerException
, it's caught by the first catch block and the rest are ignored. The finally
block always executes (unless you terminate abnormally e.g. System.exit).
So you get "x" output from the NullPointerException catch block, and "a" is output from the finally block.
A NullPointerException was thrown and it was handled and printed "x" in the console.
Then the finally statement is executed and printed "a" to the console and therefore you got the "xa".
The way try/catch works is as follow:
- The body code is executed until its end, or until an exception is thrown;
- If an exception is thrown and there is a matching catch, the code for the matching catch clause is executed;
- The finally code is always executed, whether or not an exception was thrown, and whether or not it was caught
Because you are only throwing one exception. You can create exceptions all you like, but unless you throw them they will never be caught. You never throw the generic Exception, so it can never be caught.
And by the way, there's no way to throw two exceptions at the same time. If you write:
try
{
throw new Exception();
throw new NullPointerException();
}
catch (NullPointerException e)
{
System.out.printlne("first");
}
catch (Exception e)
{
System.ot.println("second");
}
The compiler will just kick you out because the second throw is unreachable code. An exception is like a GOTO.
精彩评论