日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java中子类和父类的初始化和函数调用关系

發布時間:2025/4/16 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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);} }

在查看答案之前不妨自己先想一想輸出是什么。。。。
輸出:

Sub.num 0 Sub.num 3 2 4

那么答案為什么是這個呢?這就是本節我要說的內容,首先最簡單的,我們知道在子類的構造器之前會自動添加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也就不奇怪了。
另外關于成員變量的初始化,我們可以這樣理解

public Sub(){super();成員變量初始化;this.print();num = 4;}

最后給出一個初始化的順序:

父類的靜態成員初始化 -> 父類的靜態代碼塊 -> 子類的靜態成員初始化 -> 子類的靜態代碼塊 -> 父類的代碼塊 -> 父類的構造方法 -> 子類的代碼塊 -> 子類的構造方法 另外:靜態成員的初始化和靜態代碼塊只有在類加載的時候執行一次,再次創建實例對象的時候,不再執行了

以上就是對整個題目的理解了,困于為java初學者,以上只作為參考建議;

更新:
證實的確在子類的對象堆中會為父類無論是方法,還是域都會分配空間,無論父類的這些部分對子類是否可見。你可以將父類和子類修改為:

class Base{int num = 1;private int num2 = 10;public Base(){this.print();num = 2;num2 = 11;}public void print(){System.out.println("Base.num " + num);}public void print2(){System.out.println("Base.num2 " + num2);} }class Sub extends Base{int num = 3;public Sub(){this.print();num = 4;}public void print(){super.print2();System.out.println("Sub.num " + num);} }

預期輸出:

Base.num2 10 Sub.num 0 Base.num2 11 Sub.num 3 2 4

查看輸出的確如此,讀者可以自己分析一下。

總結

以上是生活随笔為你收集整理的java中子类和父类的初始化和函数调用关系的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。