javagenericsinheritancejlsmethod-hiding

Java non-generic method hiding generic method with intersection types


If three public interfaces are defined as:

public interface One{}
public interface Two{}
public interface Three{}

And another class, Super, is defined as:

public class Super {
    public static <E extends One & Two & Three> void hmm(E item) {}
}

Why does the following subclass of Super give a compile error?

public class Subber extends Super{
    public static void hmm(One item) {}
}

I would expect the above method to simply hide the method from Super, but that does not seem to be the case.

The JLS (8.4.8.2) says:

If a class C declares or inherits a static method m, then m is said to hide any method m', where the signature of m is a subsignature (§8.4.2) of the signature of m', in the superclasses and superinterfaces of C that would otherwise be accessible (§6.6) to code in C.

where a subsignature is defined in 8.4.2 as:

Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (§8.4.4), and, after adapting the formal parameter types of N to the the type parameters of M, the same formal parameter types.

The signature of a method m1 is a subsignature of the signature of a method m2 if either: m2 has the same signature as m1, or the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

The erasure of a type variable is the erasure of its leftmost bound, as per JLS 4.6, so: As far as I understand, Subber's hmm method is the same as the erasure of Super's hmm method, and would therefore be a subsignature of Super's hmm, thus meaning it would hide Super's hmm. However, the error message I get (from eclipse), which doesn't seem to make sense given the above is: "The method hmm(One) of type Subber has the same erasure as hmm(E) of type Super but does not hide it." What am I missing?

Edit: The precise error message, where the main method simply contains Subber.hmm(null); is:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Name clash: The method hmm(One) of type Subber has the same erasure as hmm(E) of type Super but does not hide it

    at base/testpack4.Subber.hmm(Subber.java:4)
    at base/testpack4.Main.main(Main.java:5)

Could someone explain why Subber's method does not compile, citing a credible source (preferably the JLS)?


Solution

  • ...Could someone explain why Subber's method does not compile...

    I implemented the code you listed; verbatim. And my Main.main(String[]) compiles fine with a call to Subber.hmm(null) and Subber.hmm(One).

    The only thing different I did was introduce a new Four interface that meets the requirements of the type parameter section of <E extends One & Two & Three> void Super.hmm(E).

    Then I passed an instance of Four into Subber.hmm(One) to confirm that Super.hmm(E) wasn't being called; proving it is actually hidden.

    ...citing a credible source (preferably the JLS)?...

    That implementation behaves exactly as the JLS spec that you cited describes.