MST
星途 面试题库

面试题:Java静态代码块在复杂继承体系中的行为

考虑一个Java类继承体系,父类有静态代码块、静态变量和构造函数,子类同样有静态代码块、静态变量和构造函数。当创建子类对象时,详细描述从加载类到对象创建完成整个过程中,静态代码块、静态变量初始化以及构造函数的执行顺序和交互逻辑。请通过编写具体的Java代码示例,并结合JVM规范进行深入分析。
30.8万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 执行顺序

    • 父类静态变量初始化。
    • 父类静态代码块执行。
    • 子类静态变量初始化。
    • 子类静态代码块执行。
    • 父类构造函数执行。
    • 子类构造函数执行。
  2. 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();
    }
}
  1. 结合JVM规范分析
    • 类加载阶段
      • 当JVM首次遇到需要创建Child对象的代码时,会触发类加载过程。类加载过程分为加载、验证、准备、解析和初始化五个阶段。
      • 在准备阶段,JVM为类的静态变量分配内存,并设置默认初始值(如int类型为0)。所以父类和子类的静态变量在此时都分配了内存,parentStaticVariablechildStaticVariable初始值都为0。
      • 初始化阶段,JVM按照从上到下的顺序执行类的静态变量赋值语句和静态代码块。首先执行父类的静态变量赋值parentStaticVariable = 1,然后执行父类的静态代码块,此时parentStaticVariable的值为1。接着执行子类的静态变量赋值childStaticVariable = 2,再执行子类的静态代码块,此时childStaticVariable的值为2。
    • 对象创建阶段
      • 当类加载完成后,开始创建对象。首先会调用父类的构造函数,因为在子类构造函数的第一行默认有super()语句(除非显式调用其他父类构造函数)。在父类构造函数执行前,会先执行父类的实例代码块。父类构造函数执行完成后,执行子类的实例代码块,最后执行子类的构造函数。这样就完成了子类对象的创建。