1. 程式人生 > >由一個簡單示例 引出java繼承中父子類成員變數共享問題 以及super的使用

由一個簡單示例 引出java繼承中父子類成員變數共享問題 以及super的使用

輸出結果為

12

12

13

10

虛擬機器執行步驟:

1:虛擬機器載入測試類,提取型別資訊到方法區。 2:通過儲存在方法區的位元組碼,虛擬機器開始執行main方法,main方法入棧。 3:執行main方法的第一條指令,new B(); 這句話就是給B類例項物件分配堆空間。因為B繼承A父類,所以,虛擬機器首先載入A類到方法區,並在堆中為父類成員變數在子類空間中初始化,這個過程中會建立A類的物件aa,包含A類中所有屬性方法,包含int x, f(), hh(),然後載入B類到方法區,在堆中建立B類例項化物件bb,為bb的成員變數分配空間並初始化預設值,按照繼承機制bb會繼承A類所有成員變數和方法x, f(), hh(),bb物件中會開闢三個空間宣告x, f(), hh()分別指向aa物件中的x, f(), hh()具體地址,同時額外開闢空間儲存int y和g(),所以aa物件和bb物件的x, f(), hh()這三個屬性方法是共享,但是aa和B類的x, f(), hh()並不共享,如果B類中x屬性修改為String x;或者將方法f()修改實現重寫(覆蓋),那麼子類物件bb中x或者f()不再和aa共享指向同一個引用,這時候bb會開闢空間存放x或者f()。
然後將B類的例項物件地址賦值給引用變數b。
4:之後虛擬機器先後執行b.g() b.f() a.hh(),分別入棧出棧,最後程式回到main方法,main方法執行完畢出棧,主執行緒消亡,虛擬機器例項消亡,程式結束。

下面解決幾個問題:

1.為什麼super.x輸出是12?父類的x沒有被修改啊?a.hh()的輸出可以證明

答:B繼承A的,建立B物件的時候會執行B的構造方法,圖中B的構造方法未寫出,自動呼叫無參構造,

public B(){

super();//自動呼叫A類構造方法

...

}

同時由於A中自動新增無參構造方法,也會對A的建構函式進行呼叫,建立隱含的A類物件aa,物件aa中為變數x分配了一個引用,aa和b都指向這個引用,x=x+2修改了引用裡x的值,super.x也指向這個引用,所以輸出的是修改後x的值,記住super.x指的是父類物件aa的x值 而不是父類的x值 所以super.x表示aa物件的x值 該值和bb的x值指向同一個引用。過程中建立的變數x、函式f()、hh()的引用同時給了父類和子類建立的物件,f()函式修改了x的值,即aa物件和bb物件指向的x修改了。。總的來說,super.x和bb.x是指向同一塊記憶體地址的。

2.如果在Class B中新增int X,結果會是如何?

答:在原題中B類裡面根本就沒有定義 X, 所以你引用的也是父類的 那麼當X=X+2的時候改變的也是父類物件的X 如果B類中 宣告一個int X那麼X變數被重寫(覆蓋),那麼子類物件中對x的操作只會引起bb中x的值,父類物件aa中的X就不會是12 ,而是10。此時子類中的X變數和父類的X不存在引用關係。


3.為什麼A a=new A();

a.hh()列印的是10 而不是13

答:之前對x的操作只改變了aa和bb中共享的x值,對類沒有影響,new出一個新物件是按照類進行初始化的,所以x的初始值還是10

另外:類是一個抽象的概念,物件才是具體的,子類的動作只會影響到父類的物件,你父類的屬性是不受影響的。

如都不是private 那麼子類將覆蓋父類field 子類中出現兩個field 預設的是子類.field 訪問父類field通過super.field

java中子類對父類屬性方法的繼承或者覆蓋分類:

個人總結大致5種情況:

父子都有 父有子無 父無子有
1.最普通 父類有非private的field子類無field 直接繼承 指向相同儲存空間 this.field和super.field指向同一
2. 父類有field 但是private 子類無field 直接繼承 但是field隱藏在子類不可見 無法訪問子類field 理解為子類不存在field
3.父子都有field 父類field屬性非pirvate 經典覆蓋(重寫) 無法繼承父類field 預設用自己的 子類中有兩個field空間  this.field和super.field分別執行子類field和父類field
4.父子都有field 但是父類pirvate 子類有父類private修飾的field變數 但是父類field不可見 只有自己的field可見  無法繼承 無法重寫  super.field出錯 類似於第5種  子類中field純屬額外屬性 
5.父無field 子有field 額外附加屬性方法