You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询:编译后静态代码块结构变更原因及静态变量输出0的问题

为什么静态变量打印为0且反编译后代码结构变化?

这是个非常典型的Java类初始化顺序问题,咱们结合你的代码一步步拆解清楚:

先看你的原代码与反编译代码

原代码

class Testing {
    static {
        callMe();
        System.out.println("Static finished");
    }
    static void callMe() {
        System.out.println(x);
    }
    static int x = 10;
    public static void main(String[] args) {
        System.out.println("Complete");
    }
}

反编译后的代码

class Testing {
    static int x;
    Testing() { }
    static void callMe() {
        System.out.println(x);
    }
    public static void main(String[] args) {
        System.out.println("Complete");
    }
    static {
        callMe();
        System.out.println("Static finished");
        x = 10;
    }
}

核心原因:Java类初始化的执行规则

Java虚拟机在加载类时,静态初始化的执行流程是固定的,编译器会帮你把源码转换成符合这个规则的字节码,反编译后的代码就是这个真实执行逻辑的体现:

  • 第一步:静态变量的默认初始化
    类加载时,JVM会先为所有静态变量分配内存,并赋予对应类型的默认初始值(比如int类型的默认值是0,引用类型是null)。所以不管你源码里怎么写,x在被显式赋值前,已经是0了。

  • 第二步:按顺序执行静态代码块与显式赋值
    静态代码块和静态变量的显式赋值语句,会按照它们在源码中出现的先后顺序依次执行。
    你的原代码中,静态代码块写在static int x = 10;之前,所以执行顺序是:

    1. 执行静态代码块里的callMe(),此时x只有默认值0,所以打印0
    2. 打印Static finished
    3. 执行x = 10;的显式赋值,x才变成10
  • 编译器的代码整合
    编译器会把静态变量的显式赋值语句,合并到静态初始化块的对应位置(按源码顺序)。所以反编译后的代码里,x的声明只保留了默认初始化(static int x;),而x = 10;被移到了静态代码块的最后——这其实是把源码的语法糖展开,直接呈现了JVM实际执行的逻辑。

总结

你看到的“静态代码块结构变化”,本质上是编译器将静态变量的显式赋值整合到了静态初始化流程中,让代码的执行顺序严格符合Java虚拟机的类初始化规则。原代码的写法只是语法上的便利,反编译后的代码才是JVM真正执行的“简化版”逻辑。

内容的提问来源于stack exchange,提问作者Abhishek Sahu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 23:47:31