[英]Why does line 4 only print out "B move"?
我試圖理解這段代碼的輸出。 我了解除第 4 行以外的其他輸出。
代碼:
class A{
public void move(Object o){
System.out.println("A move");
}
public void keep(String s){
System.out.println("A keep");
}
}
class B extends A{
public void move(Object o){
System.out.println("B move");
}
public void keep(Object o){
System.out.println("B keep");
}
}
class C extends B{
public void move(String s){
super.move(s);
System.out.println("C move");
}
public void keep(String s){
super.keep(s);
System.out.println("C keep");
}
}
public class main {
public static void main(String[] args) {
A a = new A();
A b = new B();
A c = new C();
a.move("Test"); //line1
b.move("Test"); //line2
b.keep("Test"); //line3
c.move("Test"); //line4
c.keep("Test"); //line5
}
}
output:
A move
B move
A keep
B move
A keep
C keep
我期待第 4 行打印出“B move.C move”,但它只是在“B move”處結束。 我認為它與第 5 行具有相同的邏輯。有人知道發生了什么嗎?
重載由編譯器決定,覆蓋在運行時完成。 一個方法的“身份”包括它的參數類型和它的返回類型以及它的名字。 所以:
因此,編譯器在第 4 行看到c.move("Test")
,並確定這是對A
類型表達式的調用(因為您將變量c
聲明為A c;
。看看 A 必須做什么報價,只有一個名為move
的方法,其簽名為void move(Object)
。因此它在 class 文件中被編碼:調用A.move(Object)
。
然后在運行時,運行時檢查void move(Object)
方法在c
變量指向的 object 的實際類型上的最具體實現,實際上是 C 類型的C
。 move(Object) 最具體的實現在 B 中:B 有一個void move(Object)
實現。 C 有一個void move(String)
,但這不算“計數”——它沒有相同的身份,實際上,它有一個不同的名字,與 A 的 move(Object) 沒有任何關系——它們有相同的實際方法名稱 ( move
) 是巧合。
兩個提示:
@Override
注釋。 如果您在此處這樣做,編譯器會告訴您例如 B 的keep(Object o)
方法不是重寫,如果您將其標記為@Override
,它還會將 C 的 move 方法標記為錯誤。 (此注釋並不意味着“此方法是重寫”。它的意思是:如果此方法未重寫或實現任何內容,則會生成編譯時錯誤。其完整簽名與父類型中的方法匹配的方法仍然會重寫它,即使沒有注釋。它只是經過編譯器檢查的文檔,這是您應該使用的好東西)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.