Generics in overridden methods
generics, java, overloading
Solution
Before the dawn of generics, Java had methods like
public class Collections
public void sort(List list) {...} [1]
And user code may have things like
public class MyList implements List ... [2]
MyList myList = ...;
Collections.sort(myList); [3]
When generics was added to Java, a decision was made to convert existing classes and methods to generic ones, without breaking any code using them. That is a great achievement in terms of difficulty, at the great price of leaving the language complicated and flawed.
So `[1]` was generified, but `[3]` must still compile as is, without having to generify `[2]`.
The hack is in §15.12.2.3
Ai can be converted by method invocation conversion (§5.3) to Si
basically saying that if the argument type (Ai) is raw, then erase the parameter type (Si) too for the purpose of matching.
Back to your example, we see why `foo(A<String>)` is considered applicable for `foo(b)`.
However there's another question - is `foo(A<String>)` applicable per [§15.12.2.2]? The answer seems to be "no" by the letter of the spec. But it may be a bug of the spec.
Problem
Ran into an interesting issue; the following class compiles: ``` public class Test { public static void main(String[] args) throws Exception { A a = new A(); B b = new B(); foo(a); foo(b); } private static void foo(A a) { System.out.println("In A"); } private static void foo(B b) { System.out.println("In B"); } private static class A {} private static class B extends A {} } ``` but this one fails: ``` public class Test { public static void main(String[] args) throws Exception { A<String> a = new A<>(); B b = new B(); foo(a); foo(b); } private static void foo(A<String> a) { System.out.println("In A"); } private static void foo(B b) { System.out.println("In B"); } private static class A<T> {} private static class B extends A {} } ``` with this error: ``` Test.java:8: error: reference to foo is ambiguous, both method foo(A<String>) in Test and method foo(B) in Test match foo(b); ^ Note: Test.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. 1 error ``` I'd have thought that due to type erasure that these would be essentially identical. Any one know what's going on here?