關於類中new物件與建構函式執行順序的問題
如下有3個類,其中COM是表示元件類別。Root類包含一個COM物件引用,Root中派生出Stem類(即Stem類繼承Root類)。每個類都有一個無引數的建構函式,列印當前的類名。其中Root類中擁有一個靜態程式碼塊。
編譯執行這個段程式碼,可以得到如下結果:package com.practise; public class Try { public static void main(String[] args) { new Root(); new Root(); new Stem(); } } class Root { Root(){System.out.println("this is Root");} static { System.out.println("我是靜態的"); //靜態變數是屬於類的,而不是屬於類建立的物件或例項。 //因為靜態變數被類的所有例項共用,所以非執行緒安全的。 //通常靜態變數還和關鍵字final一起用,作為所有物件共用的資源或常量。 } COM c; } class Stem extends Root { Stem(){System.out.println("this is Stem");} COM c=new COM("Stem"); } class COM { COM(String s){System.out.println("我是COM-----"+s);} }
/*output:
我是靜態的
this is Root
this is Root
this is Root
我是COM-----Stem
this is Stem
*/
得到這個結果的原因是什麼呢?首先從類的載入來分析,載入類檔名相同的public類,找到主函式,然後有new Root();此時需要例項化一個Root物件。
例項化Root物件時,首先應該執行靜態程式碼塊,靜態方法,靜態變數(需要注意的是靜態程式碼塊或者方法以及變數,只會隨著類的載入而只執行一次!而且是所有物件共用的資源或常量),然後申明類中非靜態成員變數,再執行建構函式,因為建構函式中可能會使用類中的成員變數。於是第一行便是列印了“我是靜態的”
第二次例項化Root物件時,便不再執行靜態程式碼塊,於是便申明一個COM類,存在棧中,初始化為null,最後執行建構函式,列印“this is Root”。
第三次是例項化一個Stem物件,在建立Stem物件時,通過extends關鍵字發現它擁有基類Root,此時應該轉到先例項化Stem的基類Root!!因為在繼承關係中,子類繼承了父類中的所有成員變數和方法,依賴於父類,(其實每個子類都擁有父類的內建物件),例項化Root類和上面一樣,建立COM物件,引用為null存在棧中(由於Root類在之前已經進行了兩次例項化,所以不會再執行靜態程式碼塊,所以的靜態程式碼塊都只加載一次),執行建構函式列印“this is Root”
然後再建立Stem物件,類中無靜態成員,於是先申明成員變數,COM c= new COM(),這個語句表明在申明變數的時候同時也進行了初始化,不再是null!由列印了“我是COM---Stem‘可以看出執行了初始化。然後再是建構函式,列印了”this is Stem“。
Java還只算得上是初學者,以上僅是個人在學習過程中的一些理解。歡迎各位發現錯誤並幫助我改正。希望自己better and better!