The Java Language Specification, section 8.4.2 writes:
It is a compile-time error to declare two methods with
override-equivalent signatures
(defined below) in a class.
Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.
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 of the signature of m2.
Clearly, the methods are not override equivalent, since ArrayList<String>
isn't ArrayList
(the erasure of ArrayList<Integer>
).
So declaring the methods is legal. Also, the method invocation expression is valid, as there trivially is a most specific method, since there is only one method matching the argument types.
Edit: Yishai correctly points out that there is another restriction closely skirted in this case. The Java Language Specification, section 8.4.8.3 writes:
It is a compile time error if a type declaration T has a member method
m1 and there exists a method m2
declared in T or a supertype of T such
that all of the following conditions
hold:
- m1 and m2 have the same name.
- m2 is accessible from T.
- The signature of m1 is not a subsignature (§8.4.2) of the signature of m2.
- m1 or some method m1 overrides (directly or indirectly) has the same erasure as m2 or some method m2 overrides (directly or indirectly).
Appendix: On ersure, and the lack thereof
Contrary to popular notion, generics in method signatures are not erased. Generics are erased in bytecode (the instruction set of the Java virtual machine). Method signatures are not part of the instruction set; they are written to the class file as specified in the source code. (As an aside, this information can also be queried at runtime using reflection).
Think about it: If type parameters were erased from class files entirely, how could the code completion in the IDE of your choice display that ArrayList.add(E)
takes a parameter of type E
, and not Object
(=the erasure of E
) if you didn't have the JDKs source code attached? And how would the compiler know to throw a compilation error when the static type of the method argument wasn't a subtype of E
?