简体   繁体   中英

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?

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM