在類的內部,變量定義的先後順序決定了初始化的順序。即變量定義散佈於方法定義之間,他們仍舊會在任何方法(包括構造器)被調用之前得到初始化。
static 修飾的是屬於類的,只有一份被對象所共有
************************************************************
************************************************************
參考:java類初始化順序
-
public
class InitialOrderTest { -
-
// 靜態變量 -
static String staticField = "靜態變量"; -
變量 -
String field = "變量"; -
-
// 靜態初始化塊 -
{ -
System.out.println(staticField); -
System.out.println("靜態初始化塊"); -
} -
-
初始化塊 -
{ -
System.out.println(field); -
System.out.println( -
} -
-
構造器 -
InitialOrderTest() { -
System.out.println( -
} -
-
static void main(String[] args) { -
InitialOrderTest(); -
} -
}
運行以上代碼,我們會得到如下的輸出結果:
- 靜態變量
- 靜態初始化塊
- 變量
- 初始化塊
- 構造器
*******************************************************
*******************************************************
思考:改變構造器 初始化塊 靜態初始化塊順序
-
public
class InitialOrderTest { -
-
// 靜態變量 -
static String staticField = "靜態變量"; -
變量 -
String field = "變量"; -
-
// 構造器 -
public -
System.out.println( -
} -
// 初始化塊 -
{ -
System.out.println(field); -
System.out.println( -
} -
// 靜態初始化塊 -
{ -
System.out.println(staticField); -
System.out.println("靜態初始化塊"); -
} -
-
static void main(String[] args) { -
InitialOrderTest(); -
} -
}
**************************
output:
靜態變量
靜態初始化塊
變量
初始化塊
構造器
***************************
結論:代碼順序的改變不會改變輸出的順序。
*******************************************************
*******************************************************
思考二:在初始化塊添加輸出靜態變量語句。
-
public
class InitialOrderTest { -
-
// 靜態變量 -
static String staticField = "靜態變量"; -
變量 -
String field = "變量"; -
-
// 靜態初始化塊 -
{ -
System.out.println(staticField); -
System.out.println("靜態初始化塊"); -
} -
-
初始化塊 -
{ -
System.out.println(field); -
System.out.println( -
System.out.println(staticField); -
} -
-
構造器 -
InitialOrderTest() { -
System.out.println( -
} -
-
static void main(String[] args) { -
InitialOrderTest(); -
} -
}
******************************
output:
靜態初始化塊
變量
初始化塊
靜態變量
構造器
******************************
疑問:輸出變了。靜態變量只輸出一次,且是初始化塊中輸出。
*******************************************************
*******************************************************
這與上文中說的完全符合。那麼對於繼承情況下又會怎樣呢?我們仍然以一段測試代碼來獲取最終結果:
-
class
Parent { -
靜態變量 -
static String p_StaticField = "父類--靜態變量"; -
變量 -
String p_Field = "父類--變量"; -
-
// 靜態初始化塊 -
{ -
System.out.println(p_StaticField); -
System.out.println("父類--靜態初始化塊"); -
} -
-
初始化塊 -
{ -
System.out.println(p_Field); -
System.out.println( -
} -
-
構造器 -
Parent() { -
System.out.println( -
} -
}
-
-
public
class SubClass extends Parent { -
靜態變量 -
static String s_StaticField = "子類--靜態變量"; -
變量 -
String s_Field = "子類--變量"; -
靜態初始化塊 -
{ -
System.out.println(s_StaticField); -
System.out.println("子類--靜態初始化塊"); -
} -
// 初始化塊 -
{ -
System.out.println(s_Field); -
System.out.println( -
} -
-
構造器 -
SubClass() { -
System.out.println( -
} -
-
程序入口 -
static void main(String[] args) { -
SubClass(); -
} -
}
運行一下上面的代碼,結果馬上呈現在我們的眼前:
- 父類--靜態變量
- 父類--靜態初始化塊
- 子類--靜態變量
- 子類--靜態初始化塊
- 父類--變量
- 父類--初始化塊
- 父類--構造器
- 子類--變量
- 子類--初始化塊
- 子類--構造器
*******************************************************
*******************************************************
-
public
class TestOrder { -
靜態變量 -
static TestA a = new TestA(); -
-
// 靜態初始化塊 -
{ -
System.out.println( -
} -
-
靜態變量 -
static TestB b = new TestB(); -
-
public static void main(String[] args) { -
TestOrder(); -
} -
}
-
-
class
TestA { -
TestA() { -
System.out.println( -
} -
}
-
-
class
TestB { -
TestB() { -
System.out.println( -
} -
}
運行上面的代碼,會得到如下的結果:
- Test--A
- 靜態初始化塊
- Test--B
*******************************************************
*******************************************************
參考:JAVA 初始化順序
//JAVA初始化分兩大步
//A、類的加載
//
//
//
//
//
//
//
//B、類的實例化
//
//
//
//
//
//
//注:類裝載步驟(詳解A步驟)
//
//裝載:查找和導入類或接口的二進制數據;
//鏈接:執行下面的校驗、準備和解析步驟,其中解析步驟是可以選擇的;
//校驗:檢查導入類或接口的二進制數據的正確性;
//準備:給類的靜態變量分配並初始化存儲空間;
//解析:將符號引用轉成直接引用;
//初始化:激活類的靜態變量的初始化Java代碼和靜態Java代碼塊。
//初始化類中屬性是靜態代碼塊的常用用途,但只能使用一次。