重写与重载编译时运行时不同之处

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

  • 先看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(),
            new ArrayList(),
            new HashMap().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 list = new ArrayList();
        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":"");

你可能感兴趣的:(java)