理解 Java 類的初始化順序對於排查繼承體系中的難以預期行為至關重要。本文透過一個父子類繼承的完整案例,詳細闡述靜態變量、靜態代碼塊、實例變量、實例代碼塊與建構子的執行時序。
public class Foo {
public Foo(String word) {
System.out.println(word);
}
}
public class Parent {
static Foo FOO = new Foo("Parent's static parameter");
Foo foo = new Foo("Parent's parameter");
static {
System.out.println("Parent's static code block");
}
{
System.out.println("Parent's code block");
}
public Parent() {
System.out.println("Parent.Parent()");
}
}
public class Child extends Parent {
static Foo FOO = new Foo("Child's static parameter");
Foo foo = new Foo("Child's parameter");
static {
System.out.println("Child's static code block");
}
{
System.out.println("Child's code block");
}
public Child() {
System.out.println("Child.Child()");
}
}
public class Run {
public static void main(String[] args) {
new Child();
}
}
Parent's static parameter Parent's static code block Child's static parameter Child's static code block Parent's parameter Parent's code block Parent.Parent() Child's parameter Child's code block Child.Child()
static Foo FOO = new Foo(...) → 輸出 "Parent's static parameter"static { ... } → 輸出 "Parent's static code block"static Foo FOO = new Foo(...) → 輸出 "Child's static parameter"static { ... } → 輸出 "Child's static code block"Foo foo = new Foo(...) → 輸出 "Parent's parameter"{ ... } (實例代碼塊) → 輸出 "Parent's code block"Foo foo = new Foo(...) → 輸出 "Child's parameter"{ ... } → 輸出 "Child's code block"一、父類靜態變量、靜態代碼塊(按順序) 二、子類靜態變量、靜態代碼塊(按順序) 三、父類實例變量、實例代碼塊(按順序) 四、父類建構子 五、子類實例變量、實例代碼塊(按順序) 六、子類建構子