淺談java中靜態(tài)方法的重寫問題詳解
首先來看看以下程序將會打印出什么:
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上調用。巴辛吉小鬣狗并不會叫喚,但是很顯然,這一只會。如果你運行該程序,就會發(fā)現(xiàn)它打印的是woof woof。這只可憐的小家伙到底出什么問題了?
問題在于bark是一個靜態(tài)方法,而對靜態(tài)方法的調用不存在任何動態(tài)的分派機制[JLS 15.12.4.4]。當一個程序調用了一個靜態(tài)方法時,要被調用的方法都是在編譯時刻被選定的,而這種選定是基于修飾符的編譯期類型而做出的,修飾符的編譯期類型就是我們給出的方法調用表達式中圓點左邊部分的名字。在本案中,兩個方法調用的修飾符分別是變量woofer和nipper,它們都被聲明為Dog類型。因為它們具有相同的編譯期類型,所以編譯器使得它們調用的是相同的方法:Dog.bark。這也就解釋了為什么程序打印出woof woof。盡管nipper的運行期類型是Basenji,但是編譯器只會考慮其編譯器類型。
要訂正這個程序,直接從兩個bark方法定義中移除掉static修飾符即可。這樣,Basenji中的bark方法將覆寫而不是隱藏Dog中的bark方法,而該程序也將會打印出woof,而不是woof woof。通過覆寫,你可以獲得動態(tài)的分派;而通過隱藏,你卻得不到這種特性。
相關文章
SpringBoot使用flyway初始化數(shù)據(jù)庫
這篇文章主要介紹了SpringBoot如何使用flyway初始化數(shù)據(jù)庫,幫助大家更好的理解和學習使用SpringBoot框架,感興趣的朋友可以了解下2021-03-03springboot與mybatis整合實例詳解(完美融合)
大家都知道springboot搭建一個spring框架只需要秒秒鐘。下面通過實例代碼給大家介紹一下springboot與mybatis的完美融合,非常不錯,具有參考借鑒價值,感興趣的朋友一起看看吧2016-09-09不調用方法實現(xiàn)hutool導出excel圖片示例詳解
這篇文章主要為大家介紹了不調用方法實現(xiàn)hutool導出excel圖片示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08