學過Java
的人都知道,Object
是全部類的父類。可是你有沒有這樣的疑問,我並無寫extends Object
,它是怎麼默認繼承Object的呢?html
那麼今天咱們就來看看像Java這種依賴於虛擬機的編程語言是怎樣實現默認繼承Object的,以及Java編譯器
和JVM
究竟是如何作的?java
首先咱們來驗證一下Object是否是全部類的父類,隨便新建一個Java類,以下圖: 編程
另外,當A類繼承MyClass類時,經過打點也能夠調到Object內的方法,這是繼承的傳遞,比如Object是MyClass的「父親」,MyClass是A類的「父親」,Object是A類的「爺爺」,間接的繼承了Object。jvm
所以,Object是超類,是全部類的父類。編程語言
要了解Java類是如何默認繼承Object的?
的緣由其實並不須要知道JVM的實現細節。只需瞭解一下對於這種虛擬機程序的基本原理便可。通常對於這種靠虛擬機運行的語言(如Java、C#等)會有兩種方法處理默認繼承問題。編輯器
在編譯源代碼時,當一個類沒有顯式標明繼承的父類時,編譯器會爲其指定一個默認的父類(通常爲Object),而交給虛擬機處理這個類時,因爲這個類已經有一個默認的父類了,所以,VM仍然會按照常規的方法像處理其餘類同樣來處理這個類。對於這種狀況,從編譯後的二進制角度來看,全部的類都會有一個父類(後面能夠以此依據來驗證)。工具
編譯器仍然按照實際代碼進行編譯,並不會作額外的處理,即若是一個類沒有顯式地繼承於其餘類時,編譯後的代碼仍然沒有父類。而後由虛擬機運行二進制代碼時,當遇到沒有父類的類時,就會自動將這個類當作是Object類的子類(通常這類語言的默認父類都是Object)。ui
從上面兩種狀況能夠看出,第1種狀況是在編譯器上作的文章,也就是說,當沒有父類時,由編譯器在編譯時自動爲其指定一個父類。第2種狀況是在虛擬機上作文章,也就是這個默認的父類是由虛擬機來添加的。命令行
那麼Java是屬於哪種狀況呢?其實這個答案很好得出。只須要隨便找一個反編譯工具,將.class文件進行反編譯便可得知編譯器是如何編譯的。code
就以上面代碼爲例,若是是第1種狀況,就算MyClass沒有父類,但因爲編譯器已經爲MyClass自動添加了一個Object父類,因此,在反編譯後獲得的源代碼中的MyClass類將會繼承Object類的。若是不是這種狀況,那麼就是第2種狀況。
那麼實際狀況是什麼樣的呢?如今咱們就將MyClass.class反編譯看看到底如何。
jd-gui反編:
CMD命令行下執行:javap MyClass>MyClass.txt
extends Object
,使用排除法,所以是第2狀況。
這樣來推導出的結論是第2種狀況,但事實真的如此嗎?爲何網上還有說反編譯後的是有extends Object
字樣?
JDK版本問題?
猜測是JDK版本的問題,因而把JDK版本切換到7,使用jd-gui和javap反編譯,接果和使用JDK8反編譯後的結果同樣,也都沒有extends Object
。
繼續換版本,昨晚在宿舍準備到Oracle官網下載JDK 6,可是死活下不來,今早到公司後第一件事就是下載,很順利,安裝後把JDK版本切換到JDK 6。
仍然在CMD窗口執行javap MyClass>MyClass.txt
,獲得的TXT文件內容以下:
extends Object
,jd-gui反編譯後的依然沒有。 即,JDK 6以前使用javap反編譯後的MyClass類顯式的繼承Object,JDK 7之後沒有;jd-gui反編譯後的無論JDK版本如何始終沒有。咱們以java自帶的工具爲準。
那麼就是說JDK 6以前是編譯器
處理,JDK 7以後是虛擬機
處理。
可是仔細想一想咱們在編輯器
裏(IDE)打點時就能列出Object類下的方法,此時還沒輪到編譯器和jvm,編輯器就已經知道MyClass類的父類是Object類了,這是由於編輯器爲咱們作了一些智能處理。
【end】
參考文獻:
java中 建立一個新的類 怎麼默認繼承Object類的: zhidao.baidu.com/question/12…