Dariusz
Dariusz

Reputation: 22251

Thrown checked exception without throws declaration in method

The following code compiles and runs on Java 13:

public class CheckedExceptionSSCE {
    
    public static void main(String[] args) {
        try {
            methodNoThrowsDeclaration();
        } catch (Exception e) {
            // why is this throw allowed?
            // no throws in main()
            throw e;
        }
    }

    private static void methodNoThrowsDeclaration() {
        System.out.println("doesn't throw");
    }
}

How come the throw e is allowed?

Is it specified somewhere in the JLS? I was not able to find it, perhaps I'm using wrong keywords to search.

Is the compiler smart enough to deduce that there will be no real checked exception thrown and thus allows the code to compile and run?

Upvotes: 3

Views: 1613

Answers (2)

dreamcrash
dreamcrash

Reputation: 51443

The method:

private static void methodNoThrowsDeclaration() {
        System.out.println("doesn't throw");
    }

does not throw any checked exception, from this SO thread one can read:

You can throw unchecked exceptions without having to declare them if you really want to. Unchecked exceptions extend RuntimeException.

therefore there is no need to adapt the main method signature.

From the Java language specification (§14.18 The throw Statement) one can read:

ThrowStatement: throw Expression ;

At least one of the following three conditions must be true, or a compile-time error occurs:

  1. The type of the Expression is an unchecked exception class (§11.1.1) or the null type (§4.1).

  2. The throw statement is contained in the try block of a try statement (§14.20) and it is not the case that the try statement can throw an exception of the type of the Expression. (In this case we say the thrown value is caught by the try statement.)

  3. The throw statement is contained in a method or constructor declaration and the type of the Expression is assignable (§5.2) to at least one type listed in the throws clause (§8.4.6, §8.8.5) of the declaration.

The code that you have shown follows at least the first condition. However, let us look at the following example, where non of those three aforementioned conditions are true, namely if you do :

private static void methodNoThrowsDeclaration() {
    System.out.println("doesn't throw");
    throw new Exception();
}

that would force you to do:

private static void methodNoThrowsDeclaration() throws Exception {
    System.out.println("doesn't throw");
    throw new Exception();
}

which in turn would give a compiler error:

Unhandled exception: java.lang.Exception

at the statement throw e;.

Upvotes: 0

greg
greg

Reputation: 1160

This is a feature that was added in Java 7. The compiler can derive the type of exception if you use a variable from the catch clause to rethrow the exception. Since you have no checked exception to be caught, it knows that e could only be RuntimeException and no throws definition is needed.

More information: https://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html

Upvotes: 3

Related Questions