javagenericsexceptionjlsthrows

Generic throws clause handling in case of overridden methods


Consider the following clause from JLS: 8.4.8.3.

If the unerased throws clause of m1 does not contain a supertype of each exception type in the throws clause of m2 (adapted, if necessary, to the type parameters of m1), a compile-time unchecked warning occurs.

Clearly - based on the other rules:

  1. the super class method must throw super-type of all exception types that the overridden class method throws.
  2. The child exception list cannot have more members than parent.

What can be the example that satisfies the above clause - that leads to unchecked warning - because based on the rules - it will outright lead to Compile time Error.


Solution

  • Here is an example:

    class Superclass<T extends Exception> {
        public void foo() throws T {}
    }
    
    class Subclass<T extends Exception> extends Superclass<T> {
        public void foo() throws Exception {}
    }
    

    T is not a supertype of Exception, so according to the quote, there should be a warning.

    Subclass.foo actually fulfils the requirements for overriding (see 8.4.8.1). Specifically, Subclass.foo has the same signature as the erasure of the inherited Superclass.foo. The inherited method is supposed to throw T, but after erasure, it throws Exception too.

    IntelliJ puts a red underline this, as if it were an error, but you can actually still compile and run the code.

    Here is what javac produces:

    % javac -J-Duser.language=en -Xlint:unchecked Superclass.java
    Superclass.java:6: warning: [unchecked] foo() in Subclass cannot override foo() in Superclass
        public void foo() throws Exception {}
                    ^
      overridden method does not throw Exception
    1 warning