面试题答案
一键面试-
执行顺序:
- 父类静态变量初始化。
- 父类静态代码块执行。
- 子类静态变量初始化。
- 子类静态代码块执行。
- 父类构造函数执行。
- 子类构造函数执行。
-
Java代码示例:
class Parent {
static int parentStaticVariable = 1;
{
System.out.println("Parent instance block");
}
static {
System.out.println("Parent static block, parentStaticVariable: " + parentStaticVariable);
}
public Parent() {
System.out.println("Parent constructor");
}
}
class Child extends Parent {
static int childStaticVariable = 2;
{
System.out.println("Child instance block");
}
static {
System.out.println("Child static block, childStaticVariable: " + childStaticVariable);
}
public Child() {
System.out.println("Child constructor");
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
}
}
- 结合JVM规范分析:
- 类加载阶段:
- 当JVM首次遇到需要创建
Child
对象的代码时,会触发类加载过程。类加载过程分为加载、验证、准备、解析和初始化五个阶段。 - 在准备阶段,JVM为类的静态变量分配内存,并设置默认初始值(如
int
类型为0)。所以父类和子类的静态变量在此时都分配了内存,parentStaticVariable
和childStaticVariable
初始值都为0。 - 初始化阶段,JVM按照从上到下的顺序执行类的静态变量赋值语句和静态代码块。首先执行父类的静态变量赋值
parentStaticVariable = 1
,然后执行父类的静态代码块,此时parentStaticVariable
的值为1。接着执行子类的静态变量赋值childStaticVariable = 2
,再执行子类的静态代码块,此时childStaticVariable
的值为2。
- 当JVM首次遇到需要创建
- 对象创建阶段:
- 当类加载完成后,开始创建对象。首先会调用父类的构造函数,因为在子类构造函数的第一行默认有
super()
语句(除非显式调用其他父类构造函数)。在父类构造函数执行前,会先执行父类的实例代码块。父类构造函数执行完成后,执行子类的实例代码块,最后执行子类的构造函数。这样就完成了子类对象的创建。
- 当类加载完成后,开始创建对象。首先会调用父类的构造函数,因为在子类构造函数的第一行默认有
- 类加载阶段: