你需要知道
- 构造函数中的第一条指令是调用其父类的构造函数,
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();
}
}
为了能够main
从类 JVM 中执行方法,Son
需要加载这个类(以及它扩展的类)的代码。类完全加载后,JVM初始化其静态内容,其中涉及执行静态块(是的,一个类中可以有多个静态块)。要完全加载Son
类,JVM 需要了解其父类的详细信息,因此它将Parent
在之前完全加载类,Son
这意味着它还将在Son
类中的静态块之前执行其静态块。
所以输出看起来像:
Parent static block
Son static block
现在在main
方法中,您正在调用Son
类构造函数new 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()
所以接下来你会看到来自 Son 构造函数的代码,之后super()
将生成
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