了解java中類各個成員的初始化順序是非常重要的,這樣你可以對類有全局的認識。不說太多,直接看下面的例子
class Father { static{ System. out.println("父類靜態代碼塊初始化" ); } { System. out.println("父類代碼塊初始化" ); } private static String s=print(); public static String print() { System. out.println("父類靜態方法" ); return "父類靜態成員變量的初始化" ; } public Father() { System. out.println("父類無參構造函數初始化完成" ); show(); } public void show() { System. out.println("父類show()方法" ); } } class Son extends Father { static{ System. out.println("子類靜態代碼塊初始化" ); } { System. out.println("子類代碼塊初始化" ); } private static int i=1; private String s="子類私有成員變量" ; public void show() { System. out.println("子類show()方法:i=" +i); } public Son() { System. out.println("子類構造函數初始化完成" ); show(); } } public class TestClassLoadSeq { public static void main(String[] args) { new Son(); } }
輸出結果:
父類靜態代碼塊初始化
父類靜態方法
子類靜態代碼塊初始化
父類代碼塊初始化
父類無參構造函數初始化完成
子類show()方法:i=1
子類代碼塊初始化
子類構造函數初始化完成
子類成員變量初始化完成:s=子類私有成員變量
子類show()方法:i=1
從結果可以看出類中各成員初始化的順序是:
1.如果類中存在繼承關系(像 Son 繼承 Father) 則首先會初始化導出類(Son)的基類(Father),然后再是導出類
2.在基類首先會初始化靜態 的東西 靜態塊>靜態變量 而且只初始化一次 (因為靜態的東西都是跟着類的加載而加載的)
3.隨后就是初始化導出類的靜態東西 跟基類的靜態初始化一樣(同上)
4.初始化基類無參構造器(調用有參就初始化有參構造器)
5.初始化導出類無參構造器(注意:導出類的成員變量和代碼塊都是是比構造函數的初始化要早。。看輸出結果可知)
在上面輸出結果大家可能會看到在基類中的構造器中調用了show() 方法,這樣的輸出可能不奇怪,我現在改一下。
1 class Father 2 { 3 private static String s= print(); 4 5 static{ 6 System. out.println("父類靜態代碼塊初始化" ); 7 } 8 { 9 System. out.println("父類代碼塊初始化" ); 10 } 11 public static String print() 12 { 13 System. out.println("父類靜態方法" ); 14 return "父類靜態成員變量的初始化" ; 15 } 16 public Father() 17 { 18 System. out.println("父類無參構造函數初始化完成" ); 19 show(); 20 } 21 public void show() 22 { 23 System. out.println("父類show()方法" ); 24 } 25 } 26 class Son extends Father 27 { 28 static{ 29 System. out.println("子類靜態代碼塊初始化" ); 30 } 31 { 32 System. out.println("子類代碼塊初始化" ); 33 } 34 private int i =1; 35 private String s="子類私有成員變量" ; 36 public void show() 37 { 38 System. out.println("子類show()方法:i=" +i); 39 } 40 public Son() 41 { 42 System. out.println("子類構造函數初始化完成" ); 43 System. out.println("子類成員變量初始化完成:s=" +s); 44 show(); 45 } 46 } 47 public class TestClassLoadSeq { 48 public static void main(String[] args) 49 { 50 new Son(); 51 } 52 53 } 54
輸出結果:
子類靜態代碼塊初始化
父類代碼塊初始化
父類無參構造函數初始化完成
子類show()方法:i=0
子類代碼塊初始化
子類構造函數初始化完成
子類成員變量初始化完成:s=子類私有成員變量
子類show()方法:i=1
可以看出跟上面的代碼沒有什么不同,唯一的不同就是我把導出類中的靜態成員變量i 變成了成員變量i,可以看出結果是截然不同,現在的結果是:0
原因:因為上面的靜態成員變量是跟着類的加載而初始化的 所以結果是1 而下面的是 成員變量又因為現在還在基類構造器中所以導出類中的成員變量還沒有得到初始化 所以是0
所以上面的初始化順序不夠完整,現在補全下:
首先jvm加載類時 會對每個對象的默認初始化 為0 ,對通過組合方式的引用類型 默認初始化為 null
總結:
java中首先初始化基類在初始化導出類(有多少個基類初始化多少個)
如果那里有錯誤希望大家幫忙提出了大家一起學習(自己也在學習中。。。。)。
提示: java中的各成員初始化的順序是非常重要的,很好的掌握對以后的學習非常有幫助