簡體   English   中英

Java動態綁定和方法覆蓋過程

[英]Java dynamic binding and method overriding process

我有點知道靜態綁定在編譯時發生而動態綁定在運行時發生的原理。 我已經閱讀了幾個相關的問題。 我可以遵循其中許多人的思路,但是當我遇到如下具體問題時,我又陷入混亂並失去了邏輯:

class Cake {
    public void taste (Cake c) {
        System.out.println("In taste of Cake class");
    }
}

class ChocolateCake extends Cake {
    public void taste(Cake c) {
        System.out.println("In taste (Cake version) of ChocolateCake class");
    }
    public void taste(ChocolateCake cc) {
        System.out.println("In taste (ChocolateCake version) of ChocolateCake class");
    }
}

class BirthdayCake extends ChocolateCake {
    public void taste(Cake c) {
        System.out.println("In taste (Cake version) of BirthdayCake class");
    }
    public void taste (ChocolateCake cc) {
        System.out.println("In taste (ChocolateCake version) of BirthdayCake class");
    }
    public void taste(BirthdayCake bc) {
        System.out.println("In taste (BirthdayCake version) of BirthdayCake class");
    }
}

已創建以下對象:

Cake c1 = new Cake();
ChocolateCake cc = new ChocolateCake();
Cake c2 = new ChocolateCake();
Cake c3 = new BirthdayCake();

輸出如下所示:

c1.taste(cc);//Output: In taste of Cake class
cc.taste(cc);//Output: In taste (ChocolateCake version) of ChocolateCake class
c2.taste(cc);//Output: In taste (Cake version) of ChocolateCake class
((BirthdayCake) c3).taste(cc);//Output: In taste (ChocolateCake version) of BirthdayCake class
((BirthdayCake) c3).taste((BirthdayCake) c3);//Output: In taste (BirthdayCake  version) of BirthdayCake class

基本上,我的問題是為什么c2.taste(cc)調用ChocolateCake類中的c2.taste(cc) taste(Cake c)方法?

這是我的想法: c2的靜態類型是Cake ,它決定了Cake中的方法將被調用。 當涉及到運行時時,c2的動態類型(即ChocolateCake )決定將調用ChocolateCake cake中的方法。 並且由於其參數類型為ChocolateCake ,因此最終將調用taste(ChocolateCake cc)

顯然,這種想法是錯誤的。 如果我假設該方法的簽名在編譯時已確定下來,因為c2的靜態類型為CakeCake類中只有一個方法。 當涉及到運行時時,它將調用ChocolateCake類中的重寫方法。 我的困惑是為什么它以這種方式而不是以前的方式工作?

我不明白的另一件事是,我們不允許編寫如下語句,因為它會導致編譯錯誤:

ChocolateCake cc = new Cake();

但是為什么ChocolateCake類型引用最終可以傳遞Cake對象,因為它應該調用ChocolateCake類中的ChocolateCake taste(Cake c)方法來獲得如上所述的正確輸出。

我認為我仍然不了解在對象引用上調用方法的整個過程。 就像在編譯時確定最佳匹配方法時發生的情況以及此后發生的情況(假設運行時)一樣(我不確定此過程中是否還有其他階段)。

誰能幫助說明這個過程? 非常感謝!

讓我嘗試簡化示例並逐步進行操作。 為了清楚起見,我還添加了@Override。

class Cake {
    public void taste (Cake c) {
        System.out.println("In taste of Cake class");
    }
}

class ChocolateCake extends Cake {
    @Override
    public void taste(Cake c) {
        System.out.println("In taste (Cake version) of ChocolateCake class");
    }
    public void taste(ChocolateCake cc) {
        System.out.println("In taste (ChocolateCake version) of ChocolateCake class");
    }
}

ChocolateCake param = new ChocolateCake();    
Cake cake = new ChocolateCake();
cake.taste(param);

當您調用cake.taste(param); Java編譯器根據引用的類型而不是引用所指向的實際對象類型來選擇要調用哪個方法的編譯時間。

的引用類型cakeCake ,所以編譯器看起來在基類Cake要被調用方法taste ,並接受Cake作為參數。 由於ChocolateCakeCake (通過繼承),因此編譯器會找到匹配項。

因為從本質上來說,您有基本taste方法的替代,所以在運行時以及由於動態調度,JVM會解析cake引用的實際類型,即ChocolateType並調用已選擇方法的替代。

我已經嘗試使用以下main():

public static void main(String[] args)
    {
        ChocolateCake cc = new ChocolateCake();
        Cake c = new ChocolateCake();
        Cake c1 = new Cake();
        Cake c2 = new ChocolateCake();
        Cake c3 = new BirthdayCake();

        ChocolateCake c4 = new BirthdayCake();

        c1.taste(cc);
        c1.taste(c);

        c2.taste(cc);
        c2.taste(c);

        c3.taste(cc);
        c3.taste(c);

        c4.taste(cc);
        c4.taste(c);

    }

輸出是這樣的:

In taste of Cake class
In taste of Cake class
In taste (Cake version) of ChocolateCake class
In taste (Cake version) of ChocolateCake class
In taste (Cake version) of BirthdayCake class
In taste (Cake version) of BirthdayCake class
In taste (ChocolateCake version) of BirthdayCake class
In taste (Cake version) of BirthdayCake class

到目前為止,我的理解如下:

  1. 查找方法的類,取決於對象的實際類型(您可以使用動態綁定)
  2. 在該目標類中,在這種情況下,要調用的方法取決於對象的引用類型(調用方法)和該參數的引用類型。 我們從兩者中選擇一個更通用的一種(引用類型),並解釋所調用的方法。

例如

c4.taste(cc);//c4:ChocolateCake cc:ChocolateCake -> ChocolateCake version
c4.taste(c);//c4:ChocolateCake c:Cake -> Cake version

只是一些自己的理解,對Java也很新;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM