淺談java繼承中是否創(chuàng)建父類對(duì)象
1.
調(diào)用父類構(gòu)造方法是真的,但是根本沒有創(chuàng)建父類對(duì)象,只不過是調(diào)用父類構(gòu)造方法來初始化屬性。
如果說調(diào)用父類構(gòu)造方法就等于創(chuàng)建父類對(duì)象,那就真的無(wú)稽之談。
new指令開辟空間,用于存放對(duì)象的各個(gè)屬/性引用等,反編譯字節(jié)碼你會(huì)發(fā)現(xiàn)只有一個(gè)new指令,所以開辟的是一塊空間,一塊空間就放一個(gè)對(duì)象。
然后,子類調(diào)用父類的屬性,方法啥的,那并不是一個(gè)實(shí)例化的對(duì)象。
在字節(jié)碼中子類會(huì)有個(gè)u2類型的父類索引,屬于CONSTANT_Class_info類型,通過CONSTANT_Class_info的描述可以找到CONSTANT_Utf8_info,然后可以找到指定的父類啊啥的。
你的方法啊,屬性名稱都是在這個(gè)上面解析出來的,然后實(shí)際變量?jī)?nèi)容存儲(chǔ)在new出來的空間那里。。。
super這個(gè)關(guān)鍵字只不過是訪問了這個(gè)空間特定部分的數(shù)據(jù)(也就是專門存儲(chǔ)父類數(shù)據(jù)的內(nèi)存部分)。。。。。。
默認(rèn)的hashcode和equals(直接使用的==比較)都是一樣的,所以,這根本就在一個(gè)空間里,也不存在單獨(dú)的出來的父類對(duì)象。
如果說子類可以強(qiáng)行轉(zhuǎn)換成父類進(jìn)行使用,那是因?yàn)閖ava虛擬機(jī)有個(gè)靜態(tài)類型(外觀類型)和實(shí)際類型的概念。
如Object t=new Point(2,3);
那么Object屬于靜態(tài)類型(外觀類型),Point屬于實(shí)際類型。
靜態(tài)類型和實(shí)際類型在程序中都可以發(fā)生變化,區(qū)別是靜態(tài)類型的變化僅僅發(fā)生在使用時(shí)發(fā)生,而變量本身的靜態(tài)類型不會(huì)改變,并且最終的靜態(tài)類型是在編譯期間可知的;而實(shí)際變量類型的變化結(jié)果只有在運(yùn)行期間才能被確定,編譯器在編譯的時(shí)候并不知道變量的實(shí)際類型是什么。
2.
java對(duì)象的內(nèi)存布局是由對(duì)象所屬的類確定。也可以這么說,當(dāng)一個(gè)類被加載到虛擬機(jī)中時(shí),由這個(gè)類創(chuàng)建的對(duì)象的布局就已經(jīng)確定下來的啦。
Hotspot中java對(duì)象的內(nèi)存布局:
每個(gè)java對(duì)象在內(nèi)存中都由對(duì)象頭和對(duì)象體組成。
對(duì)象頭是存放對(duì)象的元信息,包括該對(duì)象所屬類對(duì)象Class的引用以及hashcode和monitor的一些信息。
對(duì)象體主要存放的是java對(duì)象自身的實(shí)例域以及從父類繼承過來的實(shí)例域,并且內(nèi)部布局滿足由下規(guī)則:
規(guī)則1:任何對(duì)象都是8個(gè)字節(jié)為粒度進(jìn)行對(duì)齊的。
規(guī)則2:實(shí)例域按照如下優(yōu)先級(jí)進(jìn)行排列:長(zhǎng)整型和雙精度類型;整型和浮點(diǎn)型;字符和短整型;字節(jié)類型和布爾類型,最后是引用類型。這些實(shí)例域都按照各自的單位對(duì)齊。
規(guī)則3:不同類繼承關(guān)系中的實(shí)例域不能混合排列。首先按照規(guī)則2處理父類中的實(shí)例域,接著才是子類的實(shí)例域。
規(guī)則4:當(dāng)父類中最后一個(gè)成員和子類第一個(gè)成員的間隔如果不夠4個(gè)字節(jié)的話,就必須擴(kuò)展到4個(gè)字節(jié)的基本單位。
規(guī)則5:如果子類第一個(gè)實(shí)例域是一個(gè)雙精度或者長(zhǎng)整型,并且父類并沒有用完8個(gè)字節(jié),JVM會(huì)破壞規(guī)則2,按照整形(int),短整型(short),字節(jié)型(byte),引用類型(reference)的順序,向未填滿的空間填充。
以上就是java對(duì)象的內(nèi)存布局的規(guī)則。
接下來說一下java對(duì)象的實(shí)例化方法,也就是常見的<init>方法。
當(dāng)我們new一個(gè)對(duì)象時(shí),其實(shí)jvm已經(jīng)把這個(gè)對(duì)象的整個(gè)空間已經(jīng)分配好,并且整個(gè)對(duì)象的實(shí)例域布局已經(jīng)確定下來啦。
實(shí)例化方法<init>就是將對(duì)象實(shí)例域的值設(shè)置到相應(yīng)空間中。
<init>方法以調(diào)用父類的<init>方法開始,以自身構(gòu)造方法作為結(jié)束。實(shí)例域的聲明與實(shí)例初始化語(yǔ)句塊的位置關(guān)系會(huì)影響編譯器生成的<init>方法的字節(jié)碼順序。
還是以一個(gè)例子說明一下:
class Parent { private short six; private int age; } class Sub extend Parent{ private String name; private int age; private float price; }
當(dāng)前Sub對(duì)象的內(nèi)存布局由下:
super所謂的父類存儲(chǔ)空間的表示到底是什么意思?
這里的super存儲(chǔ)我想就是綠色的那個(gè)位置吧!
以上這篇淺談java繼承中是否創(chuàng)建父類對(duì)象就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構(gòu)建)
這篇文章主要介紹了springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構(gòu)建),需要的朋友可以參考下2020-08-08IDEA2023版本創(chuàng)建Spring項(xiàng)目只能勾選17和21卻無(wú)法使用Java8的完美解決方案
想創(chuàng)建一個(gè)springboot的項(xiàng)目,本地安裝的是1.8,但是在使用Spring Initializr創(chuàng)建項(xiàng)目時(shí),發(fā)現(xiàn)版本只有17和21,這篇文章主要介紹了IDEA2023版本創(chuàng)建Sping項(xiàng)目只能勾選17和21,卻無(wú)法使用Java8的解決方法,需要的朋友可以參考下2023-12-12SpringBoot實(shí)現(xiàn)無(wú)感刷新Token的項(xiàng)目實(shí)踐
token刷新是前端安全中必要的一部分,本文就來介紹一下SpringBoot實(shí)現(xiàn)無(wú)感刷新Token的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03解決偶現(xiàn)的MissingServletRequestParameterException異常問題
這篇文章主要介紹了解決偶現(xiàn)的MissingServletRequestParameterException問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10java通過JFrame做一個(gè)登錄系統(tǒng)的界面完整代碼示例
這篇文章主要介紹了java通過JFrame做一個(gè)登錄系統(tǒng)的界面完整代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12SpringBoot+mybatis+Vue實(shí)現(xiàn)前后端分離項(xiàng)目的示例
本文主要介紹了SpringBoot+mybatis+Vue實(shí)現(xiàn)前后端分離項(xiàng)目的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12