重寫與重載編譯時運行時不同之處

在我們平時在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<?>":"");
發佈了35 篇原創文章 · 獲贊 14 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章