JDK 1.7 onwards, throwing an exception object from catch block does not require a throws clause!!! Why is this so?

I came across a weird scenario in java today while coding around. I have a try..catch block in my method which does not have any throws clause and I am able to throw the exception object caught in the catch block. It is an object of the Exception class, hence it is not an unchecked exception. Also, It is not printing the stacktrace if exception arises instead the exception is just getting swallowed.

Below is my code example,

public class ExceptionTest {

    public void test() {
        try
        {
            // Some code which may throw exception.
        }
        catch(Exception ex)
        {
            // Compiler should ask me to have a *throws Exception* in the signature, when I am throwing an exception object.
            throw ex;
        }
    }

}

However, if I am throwing a new exception object instead of the caught exception object, compiler is asking me to have a throws clause in the method signature.

N.B: I am facing this situation when running in Java 7 or 8.

I am wondering, where is the thrown object going to? Anyone with any idea on this please...

Jon Skeet
people
quotationmark

You'll see this if the code in the try block can't throw any checked exception. At that point, the compiler knows that the only kind of exception caught by the catch block has to be an unchecked exception, and so it can therefore be rethrown. Note that if you assigned a different value to ex within the catch block, the compiler would no longer be able to have that assurance. At the moment, ex is effectively final.

If you try to call something that is declared to throw a checked exception within the try block, the code will fail to compile as expected.

For example:

public class ExceptionTest {

    public void test() {
        try {
            foo();
        } catch(Exception ex) {
            throw ex;
        }
    }

    public void foo() throws java.io.IOException {
    }
}

Gives an error of:

ExceptionTest.java:12: error: unreported exception IOException; must be caught or declared to be thrown
        throw ex;
        ^

As for where the exception "goes" - if the code in the try block throws an unchecked exception, it gets propagated as normal. Try this:

public class ExceptionTest {

    public static void main(String[] args) {
        test();
    }

    public static void test() {
        try {
            String x = null;
            x.length();
        } catch(Exception ex) {
            throw ex;
        }
    }
}

Running that gives the following output, as expected:

Exception in thread "main" java.lang.NullPointerException
        at ExceptionTest.test(ExceptionTest.java:10)
        at ExceptionTest.main(ExceptionTest.java:4)

JLS 11.2.2 documents what exceptions a statement can throw - your code will only compile if there are no checked exceptions that can be thrown.

people

See more on this question at Stackoverflow