Type erasure, overriding and generics

23,120

The signature of fooMethod(Class<?>) is the same as the signature of fooMethod(Class) after erasure, since the erasure of Class<?> is simply Class (JLS 4.6). Hence, fooMethod(Class) is a subsignature of the fooMethod(Class<?>) but not the opposite (JLS 8.4.2).

For overriding with instance methods you need the overriding method to be a subsignature of the overridden method (JLS 8.4.8.1). This is clearly not the case here.

Now that we have established the fact that your subclass method doesn't override the superclass method according to the JLS, let's look at the runtime implications when type erasure has occured. We now have two methods that look exactly the 'same' (same name, same parameter types) but do not override each other. If they don't override, they must be both available on the subtype as separate methods, but they have identical runtime signatures: conflict. So Java has to disallow it.

Overriding generic parameter types using raw parameter types is allowed because raw types exist just for this reason: they are a convenient mechanism with specific unsound type rules to accommodate interaction with legacy code. So the type system here will decide that the subclass method does override the superclass one, they are identical after type erasure and we can never have a conflict. As a consequence of this libraries can be generified independently of existing non-generic code.

Share:
23,120
Henrik Paul
Author by

Henrik Paul

Currently programming mainly in PHP in the spare time, but writing Java for a living. Started writing 5-liners of BASIC on a C64 when I was about 6, and hooked in programming ever since.

Updated on July 05, 2020

Comments

  • Henrik Paul
    Henrik Paul almost 4 years

    Can someone explain to me why

    @Override
    public void fooMethod(Class<?> c)
    

    doesn't override

    public void fooMethod(Class c)
    

    and gives me the following errors instead:

     - Name clash: The method fooMethod(Class<?>) 
    of type SubClass has the same erasure as fooMethod(Class) of 
    type SuperClass but  does not override it
    
     - The method fooMethod(Class<?>) of type 
    SubClass must override a superclass method
    

    ?

    Edit: "java -version" says Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b06-284). As for the code snippet, it's already above, pretty much; the above extends the one below.

  • Staale
    Staale over 15 years
    No, it's related to generic types not beeing castable. Class<List> is not a subtype of Class<Collection> - they are entirely seperate. You must use super or extends to express the relation.
  • Craig P. Motlin
    Craig P. Motlin over 13 years
    You're talking about the fact that generics are invariant in Java.
  • flodin
    flodin almost 13 years
    This answers the question but leads to a followup question: what do you do about the warning that inevitably comes when you use class in the subclass? Class is a raw type. References to generic type Class<T> should be parameterized.
  • Nathan
    Nathan about 11 years
    Annotate the parameter or method with @SuppressWarnings("rawtypes").
  • David T.
    David T. over 10 years
    @eljenso just to clarify, so if he had done public void fooMethod(Class<SomethingSpecific> c) it would be fine?