I came up with this example while studying mock exams for OCPJP certification,
(from http://www.certpal.com version 1.6 exam part 3, Flow Control, Question number 8)
public class Oak
{
public static void main(String args[])
{
try
{
Integer i =null;
i.toString();
}
catch (Exception e)
{
try
{
System.out.println("One ");
Integer i =null;
i.toString();
}
catch (Exception x)
{
System.out.println("Two ");
Integer i =null;
i.toString();
}
finally
{
System.out.println("Three ");
Integer i =null;
i.toString();
}
}
finally
{
System.out.println("Four ");
}
}
}
I am fully aware that finally blocks always execute unless there is a System.exit(), so I traced the program and decided that it will have an output like this
One Two Exception in thread “main” java.lang.NullPointerException Three Exception in thread “main” java.lang.NullPointerException Four
However, it turns out the correct output is (according to the site and Eclipse debugging)
One Two Three Four Exception in thread “main” java.lang.NullPointerException
What I’m not understanding is, where did the exception which occurs in catch block with “Two” go?
There is no catch block underneath that, shouldn’t it be thrown by the main thread too? Because it’s not catched?
That exception is effectively lost – if a finally block throws an exception, any exception which was in the course of propagating becomes irrelevant, and the result of the finally block is the new exception.
Likewise if you return in a finally block, then that overall try/catch/finally will never throw an exception.
See section 14.20.2 of the Java Language Specification for details. In particular, various bits like this: