JAVA · 执行轨迹实验

类初始化触发器与执行顺序实验室

选择一条直接代码操作,逐步观察 JVM 如何从“准备”走到“初始化”,以及原操作在何时真正执行。

范围说明:这里聚焦直接代码中的几种常见触发。Java 规范还定义了反射、方法句柄等其他主动使用情形,因此不要把这张操作表理解成全部清单。

观察对象:Config

高亮行 = 当前执行位置
class Config {  static final int DEFAULT_PORT = 8080; // 编译期常量  static int port = DEFAULT_PORT;  static {    System.out.println("静态块 A: " + port);  }  static String mode = "prod";  static int retries = 3;  static {    System.out.println("静态块 B: " + mode);  }  Config() { System.out.println("构造器"); }  static void ping() {    System.out.println(mode + ":" + port);  }}

执行轨迹

类尚未初始化

    static 字段快照

    字段 当前值 说明
    DEFAULT_PORT 8080 编译期常量
    port 不可观察 int
    mode 不可观察 String
    retries 不可观察 int

    控制台 / 观察结果

    等待执行……

    准备

    JVM 先为非编译期常量的类变量建立存储并放入默认值:int 是 0,引用是 null。

    初始化

    常量变量就绪后,普通类变量初始化器和 static 块依照源码文本顺序执行;这正是 <clinit> 的核心。

    原操作

    类初始化完成后,才继续构造实例、调用方法、读字段或写字段。写入 9090 也发生在初始化之后。

    02 · 即时检验

    别靠直觉,按执行时序判断

    每题选择后立即核对原因。

    挑战 1

    程序只执行 Config ref = null;,Config 会怎样?

    选择一个答案
    挑战 2

    第一次使用就是 Config.port = 9090;,最终 port 是多少?

    选择一个答案
    挑战 3

    哪一项单独执行时,不要求运行 Config 的初始化逻辑?

    选择一个答案

    提示:本实验假设 Config 此前尚未初始化;同一类在同一个类加载器中成功初始化后,不会因后续主动使用重复执行初始化逻辑。