淺談java中靜態方法的重寫問題詳解_java

來源:互聯網
上載者:User

首先來看看以下程式將會列印出什麼:

複製代碼 代碼如下:

class Dog {
    public static void bark() {
        System.out.print("woof ");
    }
}

class Basenji extends Dog {
    public static void bark() { }
}

public class Bark {
    public static void main(String args[]) {
        Dog woofer = new Dog();
        Dog nipper = new Basenji();
        woofer.bark();
        nipper.bark();
    }
}


隨意地看一看,好像該程式應該只列印一個woof。畢竟,Basenji擴充自Dog,並且它的bark方法定義為什麼也不做。main方法調用了bark方法,第一次是在Dog類型的woofer上調用,第二次是在Basenji類型的nipper上調用。巴辛吉小鬣狗並不會叫喚,但是很顯然,這一隻會。如果你運行該程式,就會發現它列印的是woof woof。這隻可憐的小傢伙到底出什麼問題了?

問題在於bark是一個靜態方法,而對靜態方法的調用不存在任何動態指派機制[JLS 15.12.4.4]。當一個程式調用了一個靜態方法時,要被調用的方法都是在編譯時間刻被選定的,而這種選定是基於修飾符的編譯期類型而做出的,修飾符的編譯期類型就是我們給出的方法調用運算式中圓點左邊部分的名字。在本案中,兩個方法調用的修飾符分別是變數woofer和nipper,它們都被聲明為Dog類型。因為它們具有相同的編譯期類型,所以編譯器使得它們調用的是相同的方法:Dog.bark。這也就解釋了為什麼程式列印出woof woof。儘管nipper的運行期類型是Basenji,但是編譯器只會考慮其編譯器類型。

要訂正這個程式,直接從兩個bark方法定義中移除掉static修飾符即可。這樣,Basenji中的bark方法將覆寫而不是隱藏Dog中的bark方法,而該程式也將會列印出woof,而不是woof woof。通過覆寫,你可以獲得動態指派;而通過隱藏,你卻得不到這種特性。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.