静态块与静态变量按源码从上到下顺序执行,谁在前谁先执行;父类静态成员优先于子类;初始化失败抛noclassdeffounderror;字节码中统一为方法。

静态块的执行顺序不是靠“块”或“变量”的类型区分,而是严格按源码中出现的先后位置决定——谁写在上面,谁就先执行。
静态变量与静态块交替执行
静态变量显式赋值(如 static int x = getValue();)和静态代码块(static { ... })在字节码中被合并进同一个
- 如果 static int a = 1; 在前,static { System.out.println(a); } 在后,则输出 1;
- 若反过来,static { a = 2; } 写在 static int a; 声明之后但赋值之前,编译器会报错“非法前向引用”;
- 即使只是声明 static int b;(无赋值),它在准备阶段就被设为默认值 0,但显式初始化动作仍按位置执行。
父类静态成员一定先于子类
子类首次被主动使用时,JVM 强制触发父类初始化,且必须完成后再执行子类静态部分:
- 先执行父类中所有静态变量赋值 + 静态块(按父类源码顺序);
- 再执行子类中所有静态变量赋值 + 静态块(按子类源码顺序);
- 子类静态块中可安全访问父类 public static 字段,但父类静态块不能引用子类任何静态成员(编译不通过)。
异常会导致类初始化失败
静态变量初始化表达式或静态块中一旦抛出未捕获异常(如 NullPointerException、RuntimeException),整个
- 后续任何对该类的主动使用(字段访问、方法调用、new 实例等)都会直接抛出 NoClassDefFoundError;
- 不会重试,也不会执行其后尚未运行的静态语句;
- 常见陷阱:在静态工厂方法里解析配置文件却没 try-catch 底层 IOException,导致类彻底不可用。
验证方式:打印 + 字节码观察
最直接的调试手段是加带标识的 System.out.println,配合类首次触发时机观察输出顺序:
- 在 main 第一行前访问某个静态字段(如 System.out.println(Child.flag);),就能完整触发父子类初始化流程;
- 注意区分“类加载”(ClassLoader.defineClass)和“类初始化”(
执行)——只有后者才运行静态块; - 用 javap -c 类名 查看生成的
方法,能清晰看到语句被合并后的实际执行流。











