你需要知道
- 构造函数中的第一条指令是调用其父类
super(params) 的构造函数,或者如果您想使用默认构造函数super()。如果是默认构造函数,您不必显式编写它。
- 初始化块中的代码在
super(...) 调用之后立即移动到每个构造函数
- 静态块在类初始化时执行,这是在 JVM 完全加载(及其父类)后完成的。
所以类被编译成类似这样的类。
public class Parent {
static {
System.out.println("Parent static block");
}
public Parent() {
super();
{
System.out.println("Parent initializer block");
}
System.out.println("Parent constructor");
}
}
public class Son extends Parent {
static {
System.out.println("Son static block");
}
public Son() {
super();
{
System.out.println("Son initializer block");
}
System.out.println("Son constructor");
}
public static void main(String[] args) {
new Son();
}
}
为了能够从Son 类执行main 方法,JVM 需要加载这个类(以及它扩展的类)的代码。类完全加载后,JVM 初始化它的静态内容涉及执行静态块(是的,一个类中可以有多个静态块)。要完全加载Son 类,JVM 需要了解其父类的详细信息,因此它将在Son 之前完全加载Parent 类,这意味着它还将在Son 类中的静态块之前执行其静态块。
所以输出看起来像:
Parent static block
Son static block
现在在main 方法中,您通过new Son() 调用Son 类构造函数,代码如下所示
super();
{
System.out.println("Son initializer block");
}
System.out.println("Son constructor");
由于其super()引用Parent类构造函数,即
super();// this will invoke Object constructor since Parent
// doesn't extend anything (which means it extends Object class)
{
System.out.println("Parent initializer block");
}
System.out.println("Parent constructor");
结果你会看到
Parent initializer block
Parent constructor
这会处理Parent#constructor() 与super() 一起执行,所以接下来你会看到super() 之后来自 Son 构造函数的代码,它将生成
Son initializer block
Son constructor
要查看在您使用 Son 构造函数甚至 main 方法之前会加载类,您可以在使用 Son 构造函数之前打印一些内容,例如
System.out.println("ABC // before new Son()");
new Son();
这将导致
Parent static block
Son static block
ABC // before new Son()
Parent initializer block
Parent constructor
Son initializer block
Son constructor