初始化塊
- 實際上,初始化塊是一個假象,使用javac命令編譯java類后,初始化塊會消失,初始化代碼被還原到每個構造器中代碼的最前面
- 在實例化的過程中:前面的初始化塊先執行,后面的后執行
- 初始化塊的修飾符只能是 static
- 普通初始化塊負責對對象執行初始化,靜態初始化塊負責對類執行初始化
- 初始化塊只在創建java對象時隱式的執行,在構造器之前執行
當創建java對象時,初始化順序是:
1、第一次類加載時:
-
先執行頂層父類的靜態初始化代碼,再向下追溯執行間接父類靜態初始化代碼,
最后執行直接父類靜態初始化代碼; -
靜態初始化塊和聲明靜態成員變量時指定的初始值都是給類的靜態初始化代碼,
它們的執行順序與源碼中書寫順序相同。
2、接着開始對對象實例化
- 先執行初始化塊或聲明實例變量時指定的初始值(兩者執行順序與源碼書寫順序相同),
- 再執行構造器里的代碼。
例子:
1 class Root{ 2 static { 3 System.out.println("Root的靜態初始化塊"); 4 } 5 6 { 7 System.out.println("Root的普通初始化塊"); 8 } 9 10 public Root() { 11 System.out.println("Root的無參構造器"); 12 } 13 14 } 15 16 class Mid extends Root{ 17 static { 18 System.out.println("Mid的靜態初始化塊"); 19 } 20 21 { 22 System.out.println("Mid的普通初始化塊"); 23 } 24 25 public Mid() { 26 System.out.println("Mid的無參構造器"); 27 } 28 29 public Mid(String msg) { 30 this(); 31 System.out.println("Mid的帶參構造器,其參數值:" + msg); 32 } 33 34 } 35 36 class Leaf extends Mid{ 37 static { 38 System.out.println("Leaf的靜態初始化塊"); 39 } 40 41 { 42 System.out.println("Leaf的普通初始化塊"); 43 } 44 45 public Leaf() { 46 super("瘋狂java"); 47 System.out.println("Leaf的無參構造器"); 48 } 49 } 50 51 public class Test { 52 public static void main(String[] args){ 53 new Leaf(); 54 new Leaf(); 55 } 56 }
執行結果:
Root的靜態初始化塊
Mid的靜態初始化塊
Leaf的靜態初始化塊
Root的普通初始化塊
Root的無參構造器
Mid的普通初始化塊
Mid的無參構造器
Mid的帶參構造器,其參數值:瘋狂java
Leaf的普通初始化塊
Leaf的無參構造器
Root的普通初始化塊
Root的無參構造器
Mid的普通初始化塊
Mid的無參構造器
Mid的帶參構造器,其參數值:瘋狂java
Leaf的普通初始化塊
Leaf的無參構造器
程序執行流程:
Root的靜態初始化塊 -->
Mid的靜態初始化塊 -->
Leaf的靜態初始化塊 -->
回到Test類new Leaf() -->
進入Leaf無參構造 -->
super進入Mid有參構造 -->
this進入MId無參構造 -->
super進入Root無參構造 -->
進入Root初始化塊執行打印 -->
進入Super無參構造並執行打印 -->
進入Mid普通初始化塊執行打印 -->
進入MId無參構造並執行打印 -->
進入Mid有參構造執行打印 -->
進入Leaf初始化塊打印 -->
進入Leaf無參構造打印 --> .........