在我们平时在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<?>":"");