本文实例使用的 Java 版本:

1
2
3
4
$ java -version
openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.8+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.8+10, mixed mode)

TL; DR

Java 类中的初始化顺序为:

父类静态变量 -> 父类静态代码块

-> 子类静态变量 -> 子类静态代码块

-> 父类变量 -> 父类代码块 -> 父类构造函数

-> 子类变量 -> 子类代码块 -> 子类构造函数 。

验证代码

父类:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package initOrder;

public class Parent {
    static String staticField = "parent static field";
    static {
        System.out.println(staticField);
        System.out.println("parent static code block");
    }

    String field = "parent field";
    {
        System.out.println(field);
        System.out.println("parent code block");
    }

    // constructor
    public Parent() {
        System.out.println("parent constructor");
    }

    // override function
    public void func() {
        System.out.println("parent function");
    }
}

子类:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package initOrder;

public class Child extends Parent {
    static String staticField = "child static field";
    static {
        System.out.println(staticField);
        System.out.println("child static code block");
    }

    String field = "child field";
    {
        System.out.println(field);
        System.out.println("child code block 1");
    }

    // constructor
    public Child() {
        System.out.println("child constructor");
    }

    // override function
    @Override
    public void func() {
        System.out.println("child function");
    }

    public static void main(String[] args) {
        System.out.println("child main function");
        new Child();
    }
    
    static {
        System.out.println("child static code block 2");
    }
}

若我们运行 Child 中的 main 函数,输出如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
parent static field
parent static code block
child static field
child static code block
child static code block 2
child main function
parent field
parent code block
parent constructor
child field
child code block
child constructor

可见,Child 中的 main 函数,在静态块初始化之后,在类变量初始化之前。

我们在这两个类之外编写 main 函数,如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import initOrder.Child;

public class testInitOrder {
    public static void main(String[] args) {
        System.out.println("main function start");
        Child child = new Child();
        child.func();
        System.out.println("main function end");
    }
}

最后输出如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
main function start
parent static field
parent static code block
child static field
child static code block
child static code block 2
parent field
parent code block
parent constructor
child field
child code block
child constructor
child function
main function end

可见,其遵循 静态变量、静态块、变量、代码块、构造函数 的初始化顺序。

Reference

  1. Java 类初始化顺序 https://segmentfault.com/a/1190000004527951

知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。