Erasure means that all occurences of generic type T
(String
in case of C) are replaced by Object
(+ required type casts). As type informations are lost this way, there is a conflict in the example - the JVM would not be able to decide which method to call.
edit(this is wrong): afaik : A subsignature would be a method that accepts a compatible type (e.g. a super type of String) and/or returns a covariant type.
I tried it out and it is confusing, but came to this explanation: The compiler does not erase, but replace generic signatures. Therefore, when D extends C<String>
the signature of the overriden C<String>.id
becomes: String id(String x)
. Clearly D
's method id
has not the same signature and also not the same erasure (because String
is not a generic type). Therefore the signature of D.id
is not a subsignature of C
. (That matches rule 3)
On the other hand, the erasure of C<T>.id(T x)
is Object id(Object x)
and identical to the erasure of D.id(Object x)
. (That matches rule 4)
Following that, it would be valid to override id
if one could keep the signatures and erasures aligned. And apparently that is possible (although not really useful):
class Foo<T> {
public void set(final T thing) {}
}
class Bar<T> extends Foo<T> {
@Override
public void set(final Object thing) {}
}
This compiles in eclipse without warning.