
http://www.cnblogs.com/miniwiki/archive/2011/03/25/1995615.html
```
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. 構造器
```
```
class Parent {
// 靜态變量
public static String p_StaticField = "父類--靜态變量";
// 變量
public String p_Field = "父類--變量";
protected int i = 9;
protected int j = 0;
// 靜态初始化塊
static {
System.out.println(p_StaticField);
System.out.println("父類--靜态初始化塊");
}
// 初始化塊
{
System.out.println(p_Field);
System.out.println("父類--初始化塊");
}
// 構造器
public Parent() {
System.out.println("父類--構造器");
System.out.println("i=" + i + ", j=" + j);
j = 20;
}
}
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("子類--構造器");
System.out.println("i=" + i + ",j=" + j);
}
// 程式入口
public static void main(String[] args) {
System.out.println("子類main方法");
new SubClass();
}
}
運作一下上面的代碼,結果馬上呈現在我們的眼前:
父類--靜态變量
父類--靜态初始化塊
子類--靜态變量
子類--靜态初始化塊
子類main方法
父類--變量
父類--初始化塊
父類--構造器
i=9, j=0
子類--變量
子類--初始化塊
子類--構造器
i=9,j=20
```
現在,結果已經不言自明了。子類的靜态變量和靜态初始化塊的初始化是在父類的變量、初始化塊和構造器初始化之前就完成了。
靜态變量、靜态初始化塊,變量、初始化塊初始化了順序取決于它們在類中出現的先後順序。
執行過程分析
(1)通路SubClass.main(),(這是一個static方法),于是裝載器就會為你尋找已經編譯的SubClass類的代碼(也就是SubClass.class檔案)。在裝載的過程中,裝載器注意到它有一個基類(也就是extends所要表示的意思),于是它再裝載基類。不管你創不建立基類對象,這個過程總會發生。如果基類還有基類,那麼第二個基類也會被裝載,依此類推。
(2)執行根基類的static初始化,然後是下一個派生類的static初始化,依此類推。這個順序非常重要,因為派生類的“static初始化”有可能要依賴基類成員的正确初始化。
(3)當所有必要的類都已經裝載結束,開始執行main()方法體,并用new SubClass()建立對象。
(4)類SubClass存在父類,則調用父類的構造函數,你可以使用super來指定調用哪個構造函數(也就是Beetle()構造函數所做的第一件事)。
基類的構造過程以及構造順序,同派生類的相同。首先基類中各個變量按照字面順序進行初始化,然後執行基類的構造函數的其餘部分。
(5)對子類成員資料按照它們聲明的順序初始化,執行子類構造函數的其餘部分。
from:
http://blog.sina.com.cn/s/blog_4cc16fc50100bjjp.html
```
class A{
public static A a = new A();
static {
System.out.println("static");
}
A(){
System.out.println("A");
}
{
System.out.println("no-static");
}
}
public class Test2 {
public static void main(String[] args){
A a =new A();
}
}
```
一個進階的問題:
http://www.ibm.com/developerworks/cn/java/j-lo-clobj-init/
```
public class Test2 {
//單态執行個體 一切問題皆由此行引起
private static final Test2 SINGLE_ENUM_RESOLVER = new
Test2();
private static Map CODE_MAP_CACHE;
static {
CODE_MAP_CACHE = new HashMap();
//為了說明問題,我在這裡初始化一條資料
CODE_MAP_CACHE.put("0","北京市");
}
//private, for single instance
private Test2() {
//初始化加載資料 引起問題,該方法也要負點責任
initEnums();
}
public static void initEnums() {
// ~~~~~~~~~問題從這裡開始暴露 ~~~~~~~~~~~//
if (null == CODE_MAP_CACHE) {
System.out.println("CODE_MAP_CACHE為空,問題在這裡開始暴露.");
CODE_MAP_CACHE = new HashMap();
}
CODE_MAP_CACHE.put("1", "北京市");
CODE_MAP_CACHE.put("2", "雲南省");
//..... other code...
}
public Map getCache() {
return Collections.unmodifiableMap(CODE_MAP_CACHE);
}
public static Test2 getInstance() {
return SINGLE_ENUM_RESOLVER;
}
public static void main(String[] args) {
System.out.println(Test2.getInstance().getCache());
}
}
輸出為:
CODE_MAP_CACHE為空,問題在這裡開始暴露.
{0=北京市}
```