Yihsi

Java 静态初始化块、初始化块与构造器

我们知道在 Java 中,当使用 new 操作符创建一个类的对象时,会依次调用该类的静态初始化块、初始化块和构造器。比如下面这个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Super {
// 静态初始化块
static {
System.out.println("static init block in class Super");
}
// 初始化块
{
System.out.println("init block in class Super");
}
public Super() {
System.out.println("constructor in class Super");
}
}

当使用

1
Super s = new Super();

控制台会打印出

1
2
3
static init block in class Super
init block in class Super
constructor in class Super

如果有一个类继承了 Super ,并且这个类也有静态初始化块和初始化块,像下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Sub extends Super {
// 静态初始化块
static {
System.out.println("static init block in class Sub");
}
// 初始化块
{
System.out.println("init block in class Sub");
}
public Sub() {
System.out.println("constructor in class Sub");
}
}

当使用

1
Sub sub = new Sub();

控制台会打印出什么呢?经过试验,发现控制台会有如下输出:

1
2
3
4
5
6
static init block in class Super
static init block in class Sub
init block in class Super
constructor in class Super
init block in class Sub
constructor in class Sub

这个结果有点儿出乎我的意料,于是开始查阅资料。查了资料资料才知道静态初始化块是在类加载的时候执行的,一个类被加载的时候会先加载其父类。初始化块是在调用构造器之前执行,Java 编译器会把初始化块复制到每个构造器(的最前面),它其实相当于多个构造器的公共部分。所以对于 Sub sub = new Sub(); 会有上面的输出结果。

参考

1、深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)

2、https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html