Java學習的第二篇總結!——子類和父類 深入分析,希望大家多多支持!
從內存角度去分析代碼,可以從本質上理解一門語言!
子類從父類繼承分成兩種:
1.方法的繼承:
方法的繼承,父類直接把自己的方法轉移到子類中去,當然前提是父類的方法修飾符的訪問范圍是子類可以訪問的范圍,但是如果子類已經重寫了父類的方法,這時候這個方法就不能重父類轉移到子類中。
2.成員變量的繼承 :
成員變量就會有點奇妙了,它不會從父類轉移到子類,而是保留在父類中,這就會出現,子類和父類可能同時擁有兩個相同名字的變量。
下面用一段代碼來說明這種相對比較復雜的關系:
package com.text; public class Test { public static void main(String[] args) { Father a = new Father(); Chilren b = new Chilren(); Father c = new Chilren(); a.getAge(); System.out.println(a.age); b.getAge(); System.out.println(b.age); c.getAge(); System.out.println(c.age); } } class Father { int age = 40; public void getAge() { System.out.println(age); } } class Chilren extends Father { int age = 18; public void getAge() { System.out.println(age); } } 輸出 40 40 18 18 18 40
前四個結果可以理解,但是最后兩個結果有人可能會問為什么結果會不一樣,這段代碼就體現了,成員變量繼承和方法繼承的區別。
可以得出結論:
Father c = new Chilren();
在以上父類引用指向子類對象情況下,訪問變量看的是引用類型,所以c.age是父類的成員變量,而c.getAge()訪問到的是子類Chilren的方法,所以在這個方法中用到的age變量是Chilren的變量
反正一句話,訪問變量看聲明,訪問方法看實際對象類型(new出來的類型)
接下來對代碼做部分修改
public static void main(String[] args) { Chilren b = new Chilren(); Father c = b System.out.println(b.age); System.out.println(c.age); } 輸出 18 40
b 和c 兩個引用都是指向內存中同一個對象,但是打印出來的結果卻是不同,這就說明了,內存中保存了兩個 age的值,一個是18 一個是40 。
這里就會產生一些疑問,在內存中他們是怎么存儲的?這時候會想到有個super關鍵字,通過super. 可以訪問到父類的變量和方法,這里有人會說:“super.代表的就是一個父類對象,因為他指向父類” 之前我也是這么想,但是看過一些書后知道其實不是這樣
其實super.不是“東西”,說道super.自然會想到this.,有人把他們歸為同類,其實他們大大不同
this:是一個真真實實對象,代表的就是當前對象,可以用 return this; 去返回一個對象。
super:不能一個對象,不是指向父類對象的意思,super只是修飾了他后邊的內容,告訴JVM,后面這部分內容不是當前對象所屬類的內容而已,若用return super,JVM是不允許的,是一種錯誤的語法。
public static void main(String[] args) { Chilren b = new Chilren(); Father c = b System.out.println(b.age); System.out.println(c.age); } 輸出 18 40
回歸到上面這段代碼,這里並不是說內存中有兩個對象 b 和 c ,內存中其實就只有一個 b對象 ,只是c 不僅有自己的實例 變量,同時也存在父類所定義的全部實例變量。
所以可以得出結論:在實例化一個子類的同時,系統會給子類所有實例變量分配內存,也會給他的父類的實例變量分配內存,及時父子類中存在重名的實例變量,也會兩個都分配內存的,這個時候子類只是隱藏了父類的這個變量,但還是會給它分配內存,然后可以用super來訪問屬於父類的變量。