在我们平时在java基础学习到多态的时候我们知道一个父类引用指向子类对象的时候,编译时看父类,运行时看子类。那么抱着这个认识看下下面这个demo,以及给你带来怎么样的思考?



    public class Demo3 {

public static String  classmodify(Set<?> s){
    return "set";
}
public static String  classmodify(List<?> s){
    return "List";
}
public static String  classmodify(Collection<?> s){
    return "Collection";
}
public static void main(String[] args) {
    Collection<?>[] collection={
            new HashSet<String>(),
            new ArrayList<BigDecimal>(),
            new HashMap<String,String>().values()

    };

    for (Collection<?> collection2 : collection) {
        System.out.println(classmodify(collection2));
    }

}

}


打印
Collection
Collection
Collection

   因为要调用哪个重载是在编译器做的决定,在for循环的三次中编译时期的类型都是相同的Collection,每次迭代的运行时期的类型是不相同的,但这个不影响重载方法的选择。


这里写图片描述


这个与我们多态的父类引用指向子类对象,编译时看父类,运行时看子类不同的是,在重载的方法选择过程中,对象的运行时类型并不影响哪个重载版本被执行,选择工作是在编译时期完成的,完全基于参数的编译时期的类型。
但是多态的父类引用指向子类对象与这个不一样的,举个例子。

public class Fu {
        String  name(){
            return "fu";
        }
}
public class Zi extends Fu {
        String  name(){
            return "zi";
        }
}

public class Sun extends Zi {
    String  name(){
        return "Sun";
    }
}

public static void main(String[] args) {
        ArrayList<Fu> list = new ArrayList<Fu>();
        list.add(new Fu());
        list.add(new Zi());
        list.add(new Sun());
        for (Fu item : list) {
            System.out.println(item.name());
        }
    }
}


打印结果是:

fu
zi
Sun

原因
:尽管每次循环迭代过程中编译时期的类型都是Fu,运行时是各自的类型,当调用被覆盖的方法时,对象编译时期的类型不影响哪个方法被执行

想要看这个引用的运行时类型

System.out.println(collection2 instanceof Set ?"set":collection2 instanceof List?"list":collection2 instanceof Collection<?>?"Collection<?>":"");
Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐