在子類構造函數中,發現,訪問子類構造函數時,父類也運行了。緣由是什麼呢?java
在子類的構造函數裏第一行有一個默認的隱式語句:super()函數
ExtendsDemo.javathis
class Fu { Fu() { System.out.println("fu run"); } } class Zi extends Fu { Zi() { //super(); //調用的是父類中的空參數的構造函數 System.out.println("zu run"); } } class ExtendsDemo { public static void main(String[] args) { new Zi(); } }
咱們也可訪問父類中帶有參數的構造函數:spa
class Fu { Fu(int x) { System.out.println("fu run"); } } class Zi extends Fu { Zi() { super(4); //父類有帶參數的構造函數 System.out.println("zu run"); } }
子類中全部的構造函數默認都會訪問父類中的空參數的構造函數。固然,若是子類中指定了訪問父類帶參數的構造函數,就不會訪問父類默認的構造函數(好像是廢話哈~~)code
這就意味着若是父類中沒有默認的構造函數,子類嘗試調用父類的默認構造函數,程序就會報錯:對象
class Fu { Fu(int x) //指定了新的構造函數,默認的構造函數就沒有了 { System.out.println("fu run 2"); } } class Zi extends Fu { Zi() { super(4); //父類有帶參數的構造函數 System.out.println("zu run 1"); } Zi(int x) { //super(); //默認會訪問父類的構造函數 System.out.println("zu run 2"); } } class ExtendsDemo { public static void main(String[] args) { new Zi(6); } }
因此這時候就須要在子類中指定調用父類帶參數的構造函數:blog
class Fu { Fu(int x) //指定了新的構造函數,默認的構造函數就沒有了 { System.out.println("fu run 2"); } } class Zi extends Fu { Zi() { super(4); //父類有帶參數的構造函數 System.out.println("zu run 1"); } Zi(int x) { super(x); //默認會訪問父類的構造函數 System.out.println("zu run 2"); } } class ExtendsDemo { public static void main(String[] args) { new Zi(6); } }
那是由於:子類繼承了父類,獲取到了父類中內容(屬性),因此在使用父類內容以前,要先看父類是如何對本身的內容進行初始化的,因此子類在構造對象時候,必須訪問父類的構造函數,爲了完成這個必須的動做,就在子類的構造函數中加入了super()語句、繼承
若是父類中沒有定義空參數構造函數,那麼子類的構造函數必須用super明確要調用父類中哪一個構造函數,不然子類沒法完成初始化。內存
注意:super語句必需要定義在子類構造函數的第一行,由於父類的初始化動做要先完成。class
//----------------------------------------------------------------------------------------------------------------------------------------------------------------
同時子類構造函數若是使用this調用了本類構造函數時,那麼super就沒有了,由於super和this都只能定義在第一行,因此只能有一個,可是能夠保證的是,子類中確定會有其餘的構造函數訪問父類的構造函數。
class Fu { Fu(int x) //指定了新的構造函數,默認的構造函數就沒有了 { System.out.println("fu run 2"); } } class Zi extends Fu { Zi() { super(4); //父類有帶參數的構造函數 System.out.println("zu run 1"); } Zi(int x) { this(); //super(x); //默認會訪問父類的構造函數 System.out.println("zu run 2"); } } class ExtendsDemo { public static void main(String[] args) { new Zi(6); } }輸出:
java中任何類默認會繼承一個根類——Object,主動繼承這個類或者不繼承這個類寫法均可以。
class Fu { Fu() { super(); show(); return; } void show() { System.out.println("fu show"); } } class Zi extends Fu { int num = 8; Zi() { super(); System.out.println("zi cons num..."+num); } void show() { System.out.println("zi show..."+num); } } class Demo { public static void main(String[] args) { Zi z = new Zi(); z.show(); } }
輸出:
經過super初始化父類內容時,子類的成員變量並未顯示初始化,等super()父類初始化完畢後,才進行子類的成員變量顯式初始化。
Person p = new Person();
一、JVM會讀取指定路徑下的Person.class文件,並加載進內存。並會先加載Person的父類(若是有直接的父類的狀況下)
二、在堆內存中開闢空間,分配地址。
三、並在對象空間中,對對象中的屬性進行默認初始化。(不是顯式初始化)
四、調用對應的構造函數進行初始化。
五、在構造函數中,第一行會先調用父類的構造函數進行初始化。
六、父類初始化完畢後,在對子類的屬性進行顯式初始化。
七、再進行子類構造函數的特定初始化。
八、初始化完畢夠,將地址值賦值給引用變量。