Java类中静态内容的初始化顺序


先看下面一段代码。

class T {
    public T() {
        System.out.println("class.name");
    }
}
 
public class Test {
 
    public Test() {
        System.out.println("Test()");
    }
 
    {
        System.out.println("{}");
    }
 
    static {
        System.out.println("static{}");
    }
    private static T t = new T();
 
    public static void main(String[] args) throws Exception {
        new Test();
    }
}

运行结果是:

static{}
class.name
{}
Test()

如果交换静态代码块和静态变量的顺序,执行结果的顺序也会交换。

public class Test {
        // …… 省却部分代码
    private static T t = new T();
 
    static {
        System.out.println("static{}");
    }
        // …… 省却部分代码
}

运行结果是:

class.name
static{}
{}
Test()

可见,在类的初始化过程中,不论是静态代码块,还是静态变量,初始化的顺序跟代码的顺序有关。


简单类的初始化过程大致如下:

① 初始化静态内容,静态内容的初始化顺序与代码的书写顺序有关;

② 初始化非静态代码块;

③ 初始化构造函数。


子父类继承的时候代码的初始化过程如下:

① 初始化父类静态内容;

② 初始化子类静态内容

③ 初始化父类非静态代码块

④ 初始化父类构造函数

⑤ 初始化子类非静态代码块

⑥ 初始化子类构造函数


测试代码:

class Parent {

    {
        System.out.println("5 父类代码块");
    }
    static {
        System.out.println("1 父类静态代码块");
    }
 
    static Sysout Sysout = new Sysout("2 父类静态变量");
 
    public Parent() {
        System.out.println("6 父类构造函数");
    }
}
 
class Sysout {
    public Sysout(String name) {
 
        System.out.println(name);
    }
 
}
 
class Child extends Parent {
    static Sysout Sysout = new Sysout("3 子类静态变量");
 
    {
        System.out.println("7 子类代码块");
    }
    static {
        System.out.println("4 子类静态代码块");
    }
 
    public Child() {
        System.out.println("8 子类构造函数");
    }
}
 
public class StaticIniBlockOrderTest {
    public static void main(String[] args) {
        new Child();
    }
}

执行结果:

1 父类静态代码块
2 父类静态变量
3 子类静态变量
4 子类静态代码块
5 父类代码块
6 父类构造函数
7 子类代码块
8 子类构造函数


PS:

静态初始化的控制权是在Java手中,这么做可能导致混乱,特别是当有许多类牵涉其中的时候,这么做常常会造成一些微妙的、不容易发现的和初始化次序有关的Bug。——《Head First 设计模式》P184



你可能感兴趣的:(Java类中静态内容的初始化顺序)