Why a less appropriate overloaded method is called
The result of running main is:
"Collection<?>". Why doesn't he call a method with ArrayList<Integer> ?
import java.util.*; public final class GenericClass<T> { private void overloadedMethod(Collection<?> o) { System.out.println("Collection<?>"); } private void overloadedMethod(List<Number> o) { System.out.println("List<Number>"); } private void overloadedMethod(ArrayList<Integer> o) { System.out.println("ArrayList<Integer>"); } public void method(List<T> l) { overloadedMethod(l); } public static void main(String[] args) { GenericClass<Integer> test = new GenericClass<Integer>(); ArrayList l = new ArrayList<Integer>(); test.method(l); } } Since l is a List , the only matching function is the first. Overload resolution is performed at compile time, and not at run time. The value of l not taken into account, only its type.
As for the language, it could also be:
List l = foo(); test.method(1); It does not matter what value is set to l .
overloadedMethod(ArrayList<Integer> o) not suitable because the declared parameter type of parameter l is List not ArrayList , and overloading is not performed for dynamic types.
overloadedMethod(List<Number> o) not suitable because the arguments of the general type do not match. Java does not have covariant or contravariant generics such as C #, so List<Number> and List<Integer> not subtype related.
The best overload is therefore overloadedMethod(Collection<?> o) , since the other two do not match.
This permission is executed at compile time:
Type l is a list
but it cannot be compared with
List and ArrayList because 'T' does not match the specific 'Number' and 'Integer'
It can only be matched with another generic type '?' and superclass 'Collection'
So, in this case, the resolution is not determined by the data structure, but by generics.