So, I was trying to write a method to answer one of my previous questions: How can I find out if an arbitrary java.lang.Method overrides another one? To do that, I was reading through the JLS, and there are some parts that seem to be missing in one case.
Imagine you have the following classes:
public class A<T> {
public void foo(T param){};
}
public class B extends A<String> {
public void foo(String param){};
}
In this case, it is quite obvious that B.foo
overrides A.foo
, however I don't understand how this case fits the specification.
Regarding method overriding, the JLS §8.4.8.1 states:
An instance method m1, declared in class C, overrides another instance method m2, declared in class A iff all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either:
- m2 is public, protected, or declared with default access in the same package as C,or
- m1 overrides a method m3 (m3 distinct from m1, m3 distinct from m2), such that m3 overrides m2.
Obviously points 1 and 3 are satisfied in our case. Let's look a bit deeper in the JLS what subsignature means. The JLS §8.4.2 says:
Two methods have the same signature if they have the same name and argument types.
Two method or constructor declarations M and N have the same argument types if all of the following conditions hold:
They have the same number of formal parameters (possibly zero)
They have the same number of type parameters (possibly zero)
Let A1, ..., An be the type parameters of M and let B1, ..., Bn be the type parameters of N. After renaming each occurrence of a Bi in N's type to Ai, the bounds of corresponding type variables are the same, and the formal parameter types of M and N are the same.
In our case, point 1 is clearly true (both have 1 argument).
Point 2 is a bit more muddy (and that's where I'm not sure what the spec means exactly): Neither of the methods declare their own type parameters, but A.foo
uses T
which is a type variable that paramterizes the class.
So my first question is: in this context, do Type variables declared in the class count or not?
Ok, now let's assume that T
doesn't count and that therefore point 2 is false (I don't know how I could even apply point 3 in this case). Our two methods do not have the same signature, but that doesn't prevent B.foo
from being a subsignature of A.foo
.
A little further in JLS §8.4.2 it says:
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.
We have already determined that point 1 is false.
The erasure signature of a method according to JLS §4.6 is a signature consisting of the same name as s and the erasures of all the formal parameter types given in s
. So the erasure of A.foo is foo(Object)
and the erasure of B.foo is foo(String)
. These two are different signatures, therefore point 2 is also false, and B.foo is not a subsignature of A.foo, and therefore B.foo does not override A.foo.
Except it does...
What am I missing? Is there some piece of the puzzle that I'm not seeing, or is the spec really not complete in this case?