簡體   English   中英

為什么第 4 行只打印出“B move”?

[英]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 行具有相同的邏輯。有人知道發生了什么嗎?

重載由編譯器決定,覆蓋在運行時完成。 一個方法的“身份”包括它的參數類型和它的返回類型以及它的名字。 所以:

  • B.keep不會覆蓋 A.keep,但 B.move覆蓋 A.move。
  • C.move不會覆蓋 B.move/A.move。 C.keep 覆蓋 A.keep 但不覆蓋 B.keep。

因此,編譯器在第 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.

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