Today I stumbled upon something interesting.
Assume the following Java 6 class:
public class Ereasure {
public Object get(Object o) {
return null; // dummy
}
public static class Derived<T> extends Ereasure{
// (1)
@Override
public Object get(T o) {
return super.get(o);
}
// (2)
/*
@Override
public Object get(Object o) {
return super.get(o);
}*/
}
}
If you try to compile the above example, the compiler says
Ereasure.java:9: method does not override or implement a method from a supertype
@Override
If you remove the @Override annotation(which should not be necessary!), it says
Ereasure.java:8: name clash: get(T) in Ereasure.Derived and get(java.lang.Object) in Ereasure have the same erasure, yet neither overrides the other
This is a bit contradictional, since T should erease to Object and therefor override the parent classes get method.
If you leave (1) unannotated and uncomment (2) so (1) overloads (2) it would not work either.
Compiler output:
Ereasure.java:15: get(T) is already defined in Ereasure.Derived
public Object get(Object o) {
As a conclusion, T is being ereased to Object, but cannot override the parent get Method.
My question is now, why dooesn’t at least one of the examples compile?
At a simple guess the compiler does not use the generic view when calculating overloads which of course would not make sense, because sometimes T might be Object other times its another type. The overridding would then become dependent on a moving target T which is downright wrong, especially if there were multiple methods all called “get” but with different single parameter types. In such a case it just wouldnt make sense and at a guess they chose to just keep things simple.