[英]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.