- class Parent{
- static String name = "hello";
- static {
- System.out.println("parent static block");
- }
- {
- System.out.println("parent block");
- }
- public Parent(){
- System.out.println("parent constructor");
- }
- }
- class Child extends Parent{
- static String childName = "hello";
- static {
- System.out.println("child static block");
- }
- {
- System.out.println("child block");
- }
- public Child(){
- System.out.println("child constructor");
- }
- }
- public class StaticIniBlockOrderTest {
- public static void main(String[] args) {
- new Child();//語句(*)
- }
- }
解答:當執行完語句(*)時,打印結果是這樣一個順序:parent static block,child static block,parent block,parent constructor,child block,child constructor。
分析:當執行new Child()時,它首先去看父類裏面有沒有靜態代碼塊,如果有,它先去執行父類裏面靜態代碼塊裏面的內容,當父類的靜態代碼塊裏面的內容執行完畢之後,接着去執行子類(自己這個類)裏面的靜態代碼塊,當子類的靜態代碼塊執行完畢之後,它接着又去看父類有沒有非靜態代碼塊,如果有就執行父類的非靜態代碼塊,父類的非靜態代碼塊執行完畢,接着執行父類的構造方法;父類的構造方法執行完畢之後,它接着去看子類有沒有非靜態代碼塊,如果有就執行子類的非靜態代碼塊。子類的非靜態代碼塊執行完畢再去執行子類的構造方法,這個就是一個對象的初始化順序。
總結:對象的初始化順序:首先執行父類靜態的內容,父類靜態的內容執行完畢後,接着去執行子類的靜態的內容,當子類的靜態內容執行完畢之後,再去看父類有沒有非靜態代碼塊,如果有就執行父類的非靜態代碼塊,父類的非靜態代碼塊執行完畢,接着執行父類的構造方法;父類的構造方法執行完畢之後,它接着去看子類有沒有非靜態代碼塊,如果有就執行子類的非靜態代碼塊。子類的非靜態代碼塊執行完畢再去執行子類的構造方法。總之一句話,靜態代碼塊內容先執行,接着執行父類非靜態代碼塊和構造方法,然後執行子類非靜態代碼塊和構造方法。
父類Static->子類static->父類缺省{}->父類構造函數->子類缺省{}->子類構造函數
注意:子類的構造方法,不管這個構造方法帶不帶參數,默認的它都會先去尋找父類的不帶參數的構造方法。如果父類沒有不帶參數的構造方法,那麼子類必須用supper關鍵子來調用父類帶參數的構造方法,否則編譯不能通過。
- 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();
- }
- }
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();
}
}
運行一下上面的代碼,結果馬上呈現在我們的眼前:
- 父類--靜態變量
- 父類--靜態初始化塊
- 子類--靜態變量
- 子類--靜態初始化塊
- 父類--變量
- 父類--初始化塊
- 父類--構造器
- 子類--變量
- 子類--初始化塊
- 子類--構造器
- public class ExA {
- private static ExA a = new ExA();
- static {
- System.out.println("父類--靜態代碼塊");
- }
- public ExA() {
- System.out.println("父類--構造函數");
- }
- {
- System.out.println("父類--非靜態代碼塊");
- }
- public static void main(String[] args) {
- new ExB();
- }
- }
- class ExB extends ExA {
- private static ExB b = new ExB();
- static {
- System.out.println("子類--靜態代碼塊");
- }
- {
- System.out.println("子類--非靜態代碼塊");
- }
- public ExB() {
- System.out.println("子類--構造函數");
- }
- }
public class ExA {
private static ExA a = new ExA();
static {
System.out.println("父類--靜態代碼塊");
}
public ExA() {
System.out.println("父類--構造函數");
}
{
System.out.println("父類--非靜態代碼塊");
}
public static void main(String[] args) {
new ExB();
}
}
class ExB extends ExA {
private static ExB b = new ExB();
static {
System.out.println("子類--靜態代碼塊");
}
{
System.out.println("子類--非靜態代碼塊");
}
public ExB() {
System.out.println("子類--構造函數");
}
}
執行結果
=====
父類--非靜態代碼塊
父類--構造函數
父類--靜態代碼塊
父類--非靜態代碼塊
父類--構造函數
子類--非靜態代碼塊
子類--構造函數
子類--靜態代碼塊
父類--非靜態代碼塊
父類--構造函數
子類--非靜態代碼塊
子類--構造函數
=====
可以發現非靜態代碼塊並不是一定在靜態代碼塊之後執行的。
我認爲此時private static ExA a = new ExA()是靜態變量。而java裏面靜態變量與靜態代碼塊是按代碼先後順序執行。所以就導致非靜態代碼塊在靜態代碼塊之前執行。