In general, erasure is not just a simple textual replacement. These different kinds of types have specific semantic meaning. Of course a language could do anything, but would the vast consequences be actually good? In general, things are disallowed because the consequences are counterproductive.
Q1. In the below code i get the error "Name clash: The method equals(T) of type Node has the same erasure as equals(Object) of type Object but does not override it"
I think the error message is just confusing you, although it is actually telling you something highly-specific. It appears to be trying to cite JLS at you.
What it means is that you've declared a method with an effectively identical signature to one in a supertype such that it would be an override, but that the override is not allowed. The message is telling you "but does not override it", because this is a fact that is mandated by the spec.
The 2nd bullet-point list in 8.4.8.3 is the stipulation that prevents your code from compiling (paraphrased):
It is a compile-time error if a type T has a method m1 and there exists a method m2 declared in a supertype of T such that:
m1 and m2 have the same name.
The signature of m1 is not a subsignature (§8.4.2) of the signature of m2.
The signature of m1 has the same erasure as the signature of m2.
Note that the complex rules in place here do allow the following override:
class A<T> {
void m(T t) {}
}
class B<T> extends A<T> {
void m(Object o) {}
}
(B.m is a subsignature of A.m, but not the other way around.)
Herein lies one problem. Say you were allowed to override the other way:
abstract class A {
abstract void put(Object o);
abstract Object get();
}
class B<T> extends A {
T t;
void put(T t) { this.t = t; }
T get() { return t; }
}
This is not really good because if we do A a = new B<String>();, we can put anything in the B<String>. It's just weird and bad. Generics are about stronger typing.
There are also more problems, for example:
class Ambiguous implements Comparable<Number>, Comparable<String> {
public int compareTo(Number n) { return 0; }
public int compareTo(String s) { return 0; }
}
Can't be done because their erasures are the same.
The whole enigma must be disallowed.
Q2. Lets say i add the @Override annotation to public boolean equals. ...
@Override does not mean you are overriding, it just means you are asserting that you think it should be an override. You just have two errors now, because it is an error to annotate a method that is not an override with @Override.
Q3. In the below code we get the error "Cannot perform instanceof check against type parameter T".
T and Object are different kinds of types. T is a type variable and Object refers to a class declaration. Specifically the rule here is that the right-hand side must be reifiable.
If it did not, if b instanceof T were simply equivalent to b instanceof |erasure of T|, would that be useful? No, it would not. In fact, it would be almost completely useless. Since we always know the bound of T we can already always make that check.
So, is the compiler complaining mainly because this is misleading ... ?
It would be extremely misleading. But let's be clear. The compiler is complaining because the language specification mandates it so. When the specification mandates something, we do not always know what its reasoning is. Just that it is so.
equals(Object). Can you clarify whether it is commented or uncommented when you get the compilation error you are asking about? Are you trying to declareequals(T)andequals(Object)in the same class, at the same time? Or is it pictured because it is 'the working example'? - Radiodef