1. 程式人生 > >java中多型的經典問題分析

java中多型的經典問題分析

Question

package demo;

/**
 * Created by zwj on 2016/3/26.
 */


class A {
    public String show(D obj) {
        return ("A and D");
    }

    public String show(A obj) {
        return ("A and A");
    }
}

class B extends A {
    public String show(B obj) {
        return ("B and B");
    }

    public String show(A obj) {
        return
("B and A"); } } class C extends B { } class D extends B { } public class ABCD { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println(a1.show(b)); // 1:a a
System.out.println(a1.show(c)); //2:a a System.out.println(a1.show(d)); //3:a d System.out.println(a2.show(b)); //4:b a System.out.println(a2.show(c)); //5:b a System.out.println(a2.show(d)); //6:a d、 System.out.println(b.show(b));//7:b b System.out.println(b.show(c)); //8:b b
System.out.println(b.show(d)); //9:a d } }

分析

首先我們要明白一個道理,對於java中的多型是編譯看左邊,執行看右邊,方法在呼叫的時候會出現兩種情況,一種是過載,另一種是子類重寫。

過載

對過載來說,java在編譯時候由編譯器已經確定要呼叫的方法,也就是說編譯器根據兩個屬性來做處理,首先是呼叫者,還有就是方法引數,通過這兩個宗量就可以確定過載呼叫的方法,方法引數看傳入的變數的靜態型別,也就是宣告型別,不是看其實際型別。

重寫

對重寫來說,java編譯時候首先編譯器會根據呼叫關係,編譯生成相對位元組碼檔案,然後根據建立物件的實際型別去呼叫相對應的子類或者父類的方法。

  1. 第一條語句,A類沒有子類,執行第一條語句時候會去A中適應查詢所以 輸出為 A and A
  2. 跟第一條一樣。
  3. 當呼叫show(D) 時候,由於A類中有宣告顯示D的方法,所以直接呼叫相對的方法,而不會根據前兩條一樣去適應。也就是方法引數的所對應方法的選擇主要看靜態型別,也就是傳入引數的宣告型別。
  4. 第四條語句,首先我們查左邊,發現a2是A型別,所以會去A方法中查詢,這時候我們找到適應的方法,也就是show(A obj) 但執行時候我們發現a2是 B型別所以會呼叫B中的相對應重寫的方法,所以輸出為 B and A
  5. 原理同第四條。
  6. 由於B中沒有重寫 show(D obj)方法所以會呼叫A中的方法做處理,因此會輸出 A and D
  7. 直接呼叫自己方法
  8. 顯而易見
  9. 跟前面分析一樣
    概括的說過載主要看傳入引數的左邊型別,重寫呼叫時候如果存在過載,則首先根據左邊型別看引數呼叫對應方法,然後再根據呼叫者的實際型別處理。