views:

192

answers:

9

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());
        }
        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");}
    }
}
+8  A: 

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.

Yishai
+6  A: 

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.

ryanprayogo
A: 

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".

Ryan Liang
+4  A: 

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.)

Bill the Lizard
A: 

The way try/catch works is as follow:

  1. The body code is executed until its end, or until an exception is thrown;
  2. If an exception is thrown and there is a matching catch, the code for the matching catch clause is executed;
  3. The finally code is always executed, whether or not an exception was thrown, and whether or not it was caught
DJClayworth
+2  A: 

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.

froadie
+2  A: 

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.

Vuntic
A: 

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.

Jay
+7  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!
polygenelubricants
You've danced all around it, but none of these examples actually answers the question.
Bill the Lizard