java static 與 static靜態程式碼塊

xiaolong_hui發表於2017-04-10
大家在去參加面試的時候,經常會遇到這樣的考題:給你兩個類的程式碼,它們之間是繼承的
關係,每個類裡只有構造器方法和一些變數,構造器裡可能還有一段程式碼對變數值進行了某
種運算,另外還有一些將變數值輸出到控制檯的程式碼,然後讓我們判斷輸出的結果。這實際
上是在考查我們對於繼承情況下類的初始化順序的瞭解。
我們大家都知道,對於靜態變數、靜態初始化塊、變數、初始化塊、構造器,它們的初始化
順序依次是(靜態變數、靜態初始化塊)>(變數、初始化塊)>構造器。我們也可以通過下
面的測試程式碼來驗證這一點:
Java 程式碼
public class InitialOrderTest {
// 靜態變數
public static String staticField = "靜態變數";
// 變數
public String field = "變數";
// 靜態初始化塊
static {
System.out.println(staticField);
System.out.println("靜態初始化塊");
}
// 初始化塊
{
System.out.println(field);
System.out.println("初始化塊");
}
// 構造器
public InitialOrderTest() {
System.out.println("構造器");
}
public static void main(String[] args) {
new InitialOrderTest();
}
}
執行以上程式碼,我們會得到如下的輸出結果:
1. 靜態變數
2. 靜態初始化塊
3. 變數
4. 初始化塊
5. 構造器
這與上文中說的完全符合。那麼對於繼承情況下又會怎樣呢?我們仍然以一段測試程式碼來獲
取最終結果:
Java程式碼 :
class Parent {
// 靜態變數
public static String p_StaticField = "父類--靜態變數";
// 變數
public String p_Field = "父類--變數";
// 靜態初始化塊
static {
System.out.println(p_StaticField);
System.out.println("父類--靜態初始化塊");
}
// 初始化塊
{
System.out.println(p_Field);
System.out.println("父類--初始化塊");
}
// 構造器
public Parent() {
System.out.println("父類--構造器");
}
}
public class SubClass extends Parent {
// 靜態變數
public static String s_StaticField = "子類--靜態變數";
// 變數
public String s_Field = "子類--變數";
// 靜態初始化塊
static {
System.out.println(s_StaticField);
System.out.println("子類--靜態初始化塊");
}
// 初始化塊
{
System.out.println(s_Field);
System.out.println("子類--初始化塊");
}
// 構造器
public SubClass() {
System.out.println("子類--構造器");
}
// 程式入口
public static void main(String[] args) {
new SubClass();
}
}
執行一下上面的程式碼,結果馬上呈現在我們的眼前:
1. 父類--靜態變數
2. 父類--靜態初始化塊
3. 子類--靜態變數
4. 子類--靜態初始化塊
5. 父類--變數
6. 父類--初始化塊
7. 父類--構造器
8. 子類--變數
9. 子類--初始化塊
10.子類--構造器
現在,結果已經不言自明瞭。大家可能會注意到一點,那就是,並不是父類完全初始化完畢
後才進行子類的初始化,實際上子類的靜態變數和靜態初始化塊的初始化是在父類的變數、
初始化塊和構造器初始化之前就完成了。
那麼對於靜態變數和靜態初始化塊之間、變數和初始化塊之間的先後順序又是怎樣呢?是否
靜態變數總是先於靜態初始化塊,變數總是先於初始化塊就被初始化了呢?實際上這取決於
它們在類中出現的先後順序。我們以靜態變數和靜態初始化塊為例來進行說明。
同樣,我們還是寫一個類來進行測試:
Java 程式碼
public class TestOrder {
// 靜態變數
public static TestA a = new TestA();
// 靜態初始化塊
static {
System.out.println("靜態初始化塊");
}
// 靜態變數
public static TestB b = new TestB();
public static void main(String[] args) {
new TestOrder();
}
}
class TestA {
public TestA() {
System.out.println("Test--A");
}
}
class TestB {
public TestB() {

System.out.println("Test--B");

執行上面的程式碼,會得到如下的結果:
1. Test--A
2. 靜態初始化塊
3. Test--B
大家可以隨意改變變數a、變數b以及靜態初始化塊的前後位置,就會發現輸出結果隨著它
們在類中出現的前後順序而改變,這就說明靜態變數和靜態初始化塊是依照他們在類中的定
義順序進行初始化的。同樣,變數和初始化塊也遵循這個規律。
瞭解了繼承情況下類的初始化順序之後,如何判斷最終輸出結果就迎刃而解了。


作者:臧圩人(zangweiren)
網址:http://zangweiren.javaeye.com



相關文章