簡體   English   中英

Java 重載和覆蓋的方法

[英]Java Overloaded AND Overridden Methods

在下面的程序中,我在 class A 中有一個方法重載了 3 次,然后在子類 B 中重載了所有 3 個重載方法。

obj3 是一個 object 引用類型 A(超類)和 object 類型 B(子類),它在執行時調用 B 的方法,這是預期的行為。

由於這段代碼中同時存在重載和覆蓋,是否意味着它在編譯時執行了 static 綁定(到 class A 中的匹配方法),然后在運行時動態綁定(到 class B 中的方法)。 它們可以同時發生嗎?

我的假設是,這是動態綁定的經典案例,因為我認為“綁定”是一種永久性行為,但同行建議它是一起的(首先是靜態的,然后是動態的)。

class A{
    
    public void method(Integer n){
        System.out.println("Integer: "+n);
    }
    
    public void method(String s){
        System.out.println("String: "+s);
    }
    
    public void method(String s, Integer n){
        System.out.println("String: "+s+" Integer: "+n);
    }
}

class B extends A{
    
    public void method(Integer n){
        System.out.println("Integer(from B): "+n);
    }
    
    public void method(String s){
        System.out.println("String(from B): "+s);
    }
    
    public void method(String s, Integer n){
        System.out.println("String(from B): "+s+" Integer(from B): "+n);
    }
}

public class Test{
    public static void main(String[] args){
        A obj1 = new A();
        B obj2 = new B();
        A obj3 = new B();
        
        System.out.println("Integer form of method");
        // Integer form of method

        System.out.println("Ref A Obj A");
        // Ref A Obj A
        obj1.method(1);
        // Integer: 1
        
        System.out.println("Ref B Obj B");
        // Ref B Obj B
        obj2.method(2);
        // Integer(from B): 2
        
        System.out.println("Ref A Obj B");
        // Ref A Obj B
        obj3.method(3);
        // Integer(from B): 3
        
    }
}

你說得對。 編譯器在 class A中的重載之間進行靜態選擇,並將該信息以方法 FQN 的形式放入.class文件中。

然后運行時在該方法的實現之間動態選擇。

由於這段代碼中同時存在重載和覆蓋,是否意味着它在編譯時執行了 static 綁定(到 class A 中的匹配方法),然后在運行時動態綁定(到 class B 中的方法)

正確的。 編譯器根據變量的類型(在本例中為A )選擇了匹配的簽名,即 static。

在運行時,Java 找到編譯器選擇的簽名的實現。 這是動態的,基於obj3 (在本例中為B )的運行時 class。

再一次嘗試說清楚:

重載

重載意味着單個 class 具有多個具有不同參數類型(又名簽名)的方法,而您恰好為它們指定了相同的名稱。 如果您將方法更改為單獨的名稱,例如 methodI methodI(Integer n)methodS(String s)methodSI(String s, Integer n)您的程序將以完全相同的方式工作。

或者,您可以想象編譯器在內部總是將 append 這樣的類型列表添加到方法名稱中。

重載由編譯器根據參數表達式編譯時類型解決。

例如,如果你寫

Object par = "Test";
a.method(par);

你得到一個編譯器錯誤。 盡管我們都看到您傳遞給方法的是一個String ,但編譯器只看到一個Object ,並且找不到匹配的方法。 只有當你要引入一個額外的method(Object o)時,編譯器才會選擇那個。 運行時會調用該方法而不是 String 版本

覆蓋

覆蓋意味着在運行時 JVM根據“點之前的對象”的運行時 class 調用方法實現。

在這種情況下,“方法”將被讀取為編譯器找到的與參數列表匹配的重載方法版本。 因此,運行時已經知道是 methodI( methodI()methodS()還是methodSI()的意思,並且只決定從哪個 class 中獲取實現。

個人觀點

允許多個方法共享相同的名稱,但參數列表不同(又名重載),會產生太多的混亂。

暫無
暫無

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

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