Java中的高级多态性

Java中的高级多态性,java,generics,polymorphism,parametric-polymorphism,Java,Generics,Polymorphism,Parametric Polymorphism,我在大学里有高级编程课程,我在理解这些代码的工作原理方面有点困难 public final class GenericClass<T> { private void overloadedMethod(Collection<?> o) { System.out.println("Collection<?>"); } private void overloadedMethod(List<Number> o) {

我在大学里有高级编程课程,我在理解这些代码的工作原理方面有点困难

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>();
        test.method(new ArrayList<Integer>());
    }
}
公共最终类GenericClass{
私有void重载方法(集合o){
系统输出打印项次(“收集”);
}
私有void重载方法(列表o){
系统输出打印项次(“列表”);
}
私有void重载方法(ArrayList o){
System.out.println(“ArrayList”);
}
公共作废方法(列表l){
超载法(l);
}
公共静态void main(字符串[]args){
GenericClass测试=新的GenericClass();
测试方法(新ArrayList());
}
}

为什么此代码打印“集合”?

方法(列表l)的声明没有指定类型T的任何边界。不能保证T是数字或数字的子类。因此,编译器只能决定此方法调用
重载方法(集合o)


请记住:编译后,类文件中不再提供有关泛型的信息。

无论何时定义泛型类型,都会自动提供相应的原始类型 这种方法

public void method(List<T> l) {

}
公共作废方法(列表l){
}
正在替换为

public void method(List<Object> l) {

}
公共作废方法(列表l){
}
如果您阅读了通配符类型,您将看到
List
List

或者
ArrayList
List
没有任何类型关系<代码>列表是
集合
的一个子类型,因此调用此方法。

当处理方法重载时,必须牢记三个概念:

  • 加宽
  • 拳击
  • Var_args
  • 您的问题在于第一点,即扩展,java编译器为这些概念中的每一个赋予优先级的顺序与上面列出的顺序相同,因此它更喜欢扩展,当您将方法调用为
    test.method(new ArrayList());
    
    编译器发现
    ArrayList()
    可以扩展到
    Collection
    ,因为它具有最高优先级,所以调用这些版本而忽略其他版本
    注意:如果您将其他两个方法的声明更改为
    private void overloadedMethod(ArrayList o)
    private void overloadedMethod(List o)
    编译器也将调用
    集合
    版本,因为它是首选的版本

    谢谢,您的答案甚至解释了更改
    overloadedMethod后的原因(列表o)
    重载方法(列表o)
    程序打印出
    列表
    而不是
    集合
    最重要的是你的最后一句话。这解释了一切!回答得很好,但是-1提醒你注意一个事实,声明
    GenericClass
    反而会导致对
    overloadedMethod(集合)的相同调用
    。所以这里还发生了一些事情。提示:只有当您更改为
    重载方法(ListNo)时,它才会起作用。如果private void重载方法(List o){//则将通过集合调用Listmethod。“@Java Player:我也一直在办公室访问这个论坛,并不断更新我自己。顺便说一句,你尝试过吗?如果你尝试过,请在这里给出结论。-1对不起,这是错误的。在指定的更改中,它将调用
    重载方法(列表)
    (它不会调用
    重载方法(ArrayList)
    因为
    方法
    需要一个
    列表
    。实际上,这里的推理不足以回答这个问题。编译器决定调用哪个方法重载,在类型擦除之前发生。