一、 代碼塊的概念
在探究對象初始化順序之前,我們先通過代碼來了解一下代碼塊的概念。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Test{ public static String str1; //靜態(tài)字段 public String str2; //普通字段 static { //靜態(tài)代碼塊 } { //構(gòu)造代碼塊 } public Test() { //構(gòu)造函數(shù) } } |
二、 創(chuàng)建子類對象時,對象的初始化順序
1. 字段初始化、代碼塊和構(gòu)造函數(shù)的執(zhí)行順序
我們先看代碼和結(jié)果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public class CodeBlockTest { public static void main(String[] args) { Child child = new Child(); } } class Father { public static String fatherStr1 = "fatherStr1(靜態(tài)字段初始化值)" ; public String fatherStr2 = "fatherStr2(字段初始化值)" ; static { System.out.println( "父類靜態(tài)代碼塊:" + fatherStr1); fatherStr1 = "fatherStr1(靜態(tài)代碼塊賦值)" ; } { System.out.println( "父類構(gòu)造代碼塊:" + fatherStr2); fatherStr2 = "fatherStr2(構(gòu)造代碼塊賦值)" ; } public Father() { System.out.println( "父類構(gòu)造函數(shù)塊:" + fatherStr2); fatherStr2 = "fatherStr2(構(gòu)造函數(shù)賦值)" ; } } class Child extends Father { public static String childStr1 = "childStr1(靜態(tài)字段初始化值)" ; public String childStr2 = "childStr2(字段初始化值)" ; static { System.out.println( "子類靜態(tài)代碼塊:" + childStr1); childStr1 = "childStr1(靜態(tài)代碼塊賦值)" ; } { System.out.println( "子類構(gòu)造代碼塊:" + childStr2); childStr2 = "childStr2(構(gòu)造代碼塊賦值)" ; } public Child() { System.out.println( "子類構(gòu)造函數(shù):" + childStr2); childStr2 = "childStr2(構(gòu)造函數(shù)賦值)" ; } } // 輸出結(jié)果: // 父類靜態(tài)代碼塊:fatherStr1(靜態(tài)字段初始化值) // 子類靜態(tài)代碼塊:childStr1(靜態(tài)字段初始化值) // 父類構(gòu)造代碼塊:fatherStr2(字段初始化值) // 父類構(gòu)造函數(shù)塊:fatherStr2(構(gòu)造代碼塊賦值) // 子類構(gòu)造代碼塊:childStr2(字段初始化值) // 子類構(gòu)造函數(shù):childStr2(構(gòu)造代碼塊賦值) |
通過每執(zhí)行一個代碼塊或構(gòu)造函數(shù),輸出字段在上一代碼塊執(zhí)行后的值,以此來探究對象的初始化順序。
由目前的輸出結(jié)果可知,對于對象的初始化順序,我們可以得出以下結(jié)論:
1. 父類靜態(tài)字段初始化
2. 父類靜態(tài)代碼塊、子類靜態(tài)字段初始化 (接下來探究兩者的順序)
3. 子類靜態(tài)代碼塊
4. 父類普通字段初始化
5. 父類構(gòu)造代碼塊
6. 父類構(gòu)造函數(shù)
7. 子類普通字段初始化
8. 子類構(gòu)造代碼塊
9. 子類構(gòu)造函數(shù)
2. 父類靜態(tài)代碼塊和子類靜態(tài)字段初始化的執(zhí)行順序
還是一樣,我們通過代碼的執(zhí)行結(jié)果來探究兩者間的執(zhí)行順序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class CodeBloacTest2 { public static void main(String[] args) { Child child = new Child(); } } class Father { public static String fatherStr = "(靜態(tài)字段初始化值)" ; static { System.out.println( "父類靜態(tài)代碼塊:fatherStr" + fatherStr); fatherStr = "(靜態(tài)代碼塊賦值)" ; } } class Child extends Father { public static String childStr = fatherStr; static { System.out.println( "子類靜態(tài)代碼塊:childStr = fatherStr" + childStr); childStr = "(靜態(tài)代碼塊賦值)" ; } } // 輸出結(jié)果: // 父類靜態(tài)代碼塊:fatherStr(靜態(tài)字段初始化值) // 子類靜態(tài)代碼塊:childStr = fatherStr(靜態(tài)代碼塊賦值) |
我們在子類靜態(tài)字段childStr初始化的時候,賦的是父類靜態(tài)字段fatherStr的值。由輸出結(jié)果可知,childStr初始化后的值是父類靜態(tài)代碼塊執(zhí)行后賦予fatherStr的值。由此可知兩者的執(zhí)行順序為:父類靜態(tài)代碼塊==>子類靜態(tài)字段初始化
三、 結(jié)論
父類靜態(tài)字段初始化
父類靜態(tài)代碼塊
子類靜態(tài)字段初始化
子類靜態(tài)代碼塊
父類普通字段初始化
父類構(gòu)造代碼塊
父類構(gòu)造函數(shù)
子類普通字段初始化
子類構(gòu)造代碼塊
子類構(gòu)造函數(shù)
通過結(jié)論我們可以很明顯的看出:static字段、代碼塊的執(zhí)行順序優(yōu)先于非static字段、代碼塊。這是因為在靜態(tài)域是屬于類的,在類加載后就一直存在;而普通域需要創(chuàng)建對象才能訪問。而在創(chuàng)建對象時,需要先加載父類,然后再加載子類,因此父類的靜態(tài)字段初始化和靜態(tài)代碼塊執(zhí)行先于子類。
以上內(nèi)容希望對各位朋友有所幫助
原文鏈接:http://blog.csdn.net/lim_dev/article/details/70161726