为什么通用版本的Collection参数正在调用

tes*_*est 8 java generics

这是一个代码段

public class HelloWorld{

    public static void main(String[] args) { 
        GenericClass<Integer> test = new GenericClass<Integer>(); 
        test.method(new ArrayList<Integer> ()); 
    } 
}
class GenericClass<T> {
    public void overloadedMethod( Collection<?> o) { 
        System.out.println("overloadedMethod(Collection<?>)"); 
    } 
    public void overloadedMethod( List<Number> s) { 
        System.out.println("overloadedMethod(List<Number>)"); 
    } 
    public void overloadedMethod( ArrayList<Integer> i) { 
        System.out.println("overloadedMethod(ArrayList<Integer>)"); 
    }

    public void method(List<T> t) { 
        overloadedMethod(t) ; // which method is called? 
    }   
}
Run Code Online (Sandbox Code Playgroud)

我期待它会使用Arraylist参数调用重载方法,但是为什么会调用Collection?

dka*_*zel 5

这个确切的代码用于Angelika Langer关于java泛型的网页中的一个例子

如果页面出现故障,我会发布解释:

程序打印:

overloadedMethod(系列)

有人可能会预期会调用ArrayList的版本,但这又是错误的期望.让我们看看编译器将泛型类转换为什么.

示例(在类型擦除之后):

public final class GenericClass {

    private void overloadedMethod( Collection o) {
        System.out.println("overloadedMethod(Collection<?>)");
    }
    private void overloadedMethod( List s) {
        System.out.println("overloadedMethod(List<Number>)");
    }
    private void overloadedMethod( ArrayList i) {
        System.out.println("overloadedMethod(ArrayList<Integer>)");
    }

    private void method(List t) {
        overloadedMethod(t) ;
    }

    public static void main(String[] args) {
        GenericClass test = new GenericClass();
        test.method(new ArrayList ());
    }
} 
Run Code Online (Sandbox Code Playgroud)

有人可能错误地认为编译器会决定重载方法的List版本是最佳匹配.但这当然是错的.重载方法的List版本最初是一个以List作为参数的版本,但在调用时会传递List,其中T可以是任何类型,不必是Number.由于T可以是任何类型,因此重载方法的唯一可行版本是Collection的版本.

实际上,如果注释掉Collection方法,则会出现编译器错误,因为List和ArrayList太具体,不适合所有可能的<T>类型.