由一個簡單示例 引出java繼承中父子類成員變數共享問題 以及super的使用
輸出結果為
12
12
13
10
虛擬機器執行步驟:
然後將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 額外附加屬性方法