java中子类和父类的初始化和函数调用关系
在開始說明之前,我們直接來看一個代碼
public class play {public static void main(String[] args) {Base base = new Sub();Sub sub = (Sub)base;System.out.println(base.num);System.out.println(sub.num);} }class Base{int num = 1;public Base(){this.print();num = 2;}public void print(){System.out.println("Base.num " + num);} }class Sub extends Base{int num = 3;public Sub(){this.print();num = 4;}public void print(){System.out.println("Sub.num " + num);} }在查看答案之前不妨自己先想一想輸出是什么。。。。
輸出:
那么答案為什么是這個呢?這就是本節我要說的內容,首先最簡單的,我們知道在子類的構造器之前會自動添加super()來調用父類的構造器。有了這個基礎,我們再討論接下來的內容。
首先在執行
Base base = new Sub();的時候,我們知道要去調用子類的構造器,那么我們來到
public Sub(){this.print();num = 4;}由于自動添加了super(),所以我們來到
public Base(){this.print();num = 2;}在我們執行this.print();之前Base類的num會先進行初始化,那么在父類中的num就等于1接下來執行this.print()的是時候,發現子類重寫了print()方法,所以去調用了Base的print()方法,這個時候子類的num為默認初始值0,也就是說還沒有初始化為3(順便一說,成員變量可以不用程序員顯式初始化就使用,但是局部變量是需要初始化再使用的),也就解釋了這一句輸出:
Sub.num 0接下來回到Base(),執行num = 2;父類的num值為2;到這里為止super()算是執行完了,接下來回到Sub();注意這個時候執行了int num = 3;對子類的num進行了初始化,所以在執行this.print()的時候,輸出的是:
Sub.num 3而后執行的是num = 4;子類的num變為4;到目前為止,我們的:
Base base = new Sub();算是執行完了;接下來的
System.out.println(base.num); System.out.println(sub.num);就不太好理解了,實際上之前說的父類num和子類num到底是什么呢?他們在java虛擬機中的什么地方呢?那么有一點java基礎的朋友都知道,成員變量隨對象的創建在堆中分配空間(順帶一提:局部變量在java虛擬機棧中分配空間),我們創建了Sub對象,那么sub對象中的num,肯定就是在分配給sub對象的堆中了。那么父類的num在哪呢?我查閱了一些網上的資料,發現有這么一句話:
https://www.cnblogs.com/zhaideyou/p/5844155.html
無論父類中的成員變量是否被子類覆蓋,子類都會擁有父類中的這些成員變量。
那么我就猜測,父類的num也是在sub對象分配的堆中存在,是的,一個堆空間中有兩個num,但是他們是屬于不同類的,我們依舊可以分辨出來,我們變量的靜態類型,在這里是:
Base base = new Sub(); //base靜態類型為Base Sub sub = (Sub)base; //sub靜態類型為Sub我們依照變量的靜態類型來訪問num,是父類的num,還是子類的num。那么輸出是2,4也就不奇怪了。
另外關于成員變量的初始化,我們可以這樣理解
最后給出一個初始化的順序:
父類的靜態成員初始化 -> 父類的靜態代碼塊 -> 子類的靜態成員初始化 -> 子類的靜態代碼塊 -> 父類的代碼塊 -> 父類的構造方法 -> 子類的代碼塊 -> 子類的構造方法 另外:靜態成員的初始化和靜態代碼塊只有在類加載的時候執行一次,再次創建實例對象的時候,不再執行了以上就是對整個題目的理解了,困于為java初學者,以上只作為參考建議;
更新:
證實的確在子類的對象堆中會為父類無論是方法,還是域都會分配空間,無論父類的這些部分對子類是否可見。你可以將父類和子類修改為:
預期輸出:
Base.num2 10 Sub.num 0 Base.num2 11 Sub.num 3 2 4查看輸出的確如此,讀者可以自己分析一下。
總結
以上是生活随笔為你收集整理的java中子类和父类的初始化和函数调用关系的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于CMSIS创建典型STM32F4工程
- 下一篇: Netty基本使用流程代码