(轉)java繼承中是否建立父類對象?,java繼承
1.
調用父類構造方法是真的,但是根本沒有建立父類對象,只不過是調用父類構造方法來初始化屬性。
如果說調用父類構造方法就等於建立父類對象,那就真的無稽之談。
new指令開闢空間,用於存放對象的各個屬/性引用等,反編譯位元組碼你會發現只有一個new指令,所以開闢的是一塊空間,一塊空間就放一個對象。
然後,子類調用父類的屬性,方法啥的,那並不是一個執行個體化的對象。
在位元組碼中子類會有個u2類型的父類索引,屬於CONSTANT_Class_info類型,通過CONSTANT_Class_info的描述可以找到CONSTANT_Utf8_info,然後可以找到指定的父類啊啥的。
你的方法啊,屬性名稱都是在這個上面解析出來的,然後實際變數內容儲存在new出來的空間那裡。。。
super這個關鍵字只不過是訪問了這個空間特定部分的資料(也就是專門儲存父類資料的記憶體部分)。。。。。。
預設的hashcode和equals(直接使用的==比較)都是一樣的,所以,這根本就在一個空間裡,也不存在單獨的出來的父類對象。
如果說子類可以強行轉換成父類進行使用,那是因為java虛擬機器有個靜態類型(外觀類型)和實際類型的概念。
如Object t=new Point(2,3);
那麼Object屬於靜態類型(外觀類型),Point屬於實際類型。
靜態類型和實際類型在程式中都可以發生變化,區別是靜態類型的變化僅僅發生在使用時發生,而變數本身的靜態類型不會改變,並且最終的靜態類型是在編譯期間可知的;而實際變數類型的變化結果只有在運行期間才能被確定,編譯器在編譯的時候並不知道變數的實際類型是什麼。
2.
java對象的記憶體布局是由對象所屬的類確定。也可以這麼說,當一個類被載入到虛擬機器中時,由這個類建立的對象的布局就已經確定下來的啦。
Hotspot中java對象的記憶體布局:
每個java對象在記憶體中都由對象頭和對象體組成。
對象頭是存放對象的元資訊,包括該對象所屬類對象Class的引用以及hashcode和monitor的一些資訊。
對象體主要存放的是java對象自身的執行個體域以及從父類繼承過來的執行個體域,並且內部布局滿足由下規則:
規則1:任何對象都是8個位元組為粒度進行對齊的。
規則2:執行個體域按照如下優先順序進行排列:長整型和雙精確度類型;整型和浮點型;字元和短整型;位元組類型和布爾類型,最後是參考型別。這些執行個體域都按照各自的單位對齊。
規則3:不同類繼承關係中的執行個體域不能混合排列。首先按照規則2處理父類中的執行個體域,接著才是子類的執行個體域。
規則4:當父類中最後一個成員和子類第一個成員的間隔如果不夠4個位元組的話,就必須擴充到4個位元組的基本單位。
規則5:如果子類第一個執行個體域是一個雙精確度或者長整型,並且父類並沒有用完8個位元組,JVM會破壞規則2,按照整形(int),短整型(short),位元組型(byte),參考型別(reference)的順序,向未填滿的空間填充。
以上就是java對象的記憶體布局的規則。
接下來說一下java對象的執行個體化方法,也就是常見的<init>方法。
當我們new一個對象時,其實jvm已經把這個對象的整個空間已經分配好,並且整個對象的執行個體域布局已經確定下來啦。
執行個體化方法<init>就是將對象執行個體域的值設定到相應空間中。
<init>方法以調用父類的<init>方法開始,以自身構造方法作為結束。執行個體域的聲明與執行個體初始化語句塊的位置關係會影響編譯器產生的<init>方法的位元組碼順序。
還是以一個例子說明一下:
class Parent {
private short six;
private int age;
}
class Sub extend Parent{
private String name;
private int age;
private float price;
}
當前Sub對象的記憶體布局由下:
super所謂的父類儲存空間的表示到底是什麼意思?
這裡的super儲存我想就是綠色的那個位置吧!