一聚教程网:一个值得你收藏的教程网站

热门教程

Java类成员初始化:静态代码块和声明处赋值的顺序

时间:2026-06-25 08:25:52 编辑:袖梨 来源:一聚教程网

静态代码块和声明处赋值按源码顺序执行,合并入<clinit>方法;父类先于子类初始化;异常导致类初始化失败并抛NoClassDefFoundError。

静态代码块和声明处赋值都属于类初始化阶段,它们的执行顺序严格按源码中出现的先后位置决定——谁写在上面,谁就先执行。

静态成员按源码顺序逐行执行

Java 把所有静态变量显式初始化(如 static int x = getValue();)和静态代码块(static { ... })合并进同一个 <clinit> 方法,JVM 按文件从上到下扫描并依次插入指令:

  • 如果静态变量声明在前,它的初始化表达式会先执行;
  • 如果静态块写在变量声明之前,块内不能引用该变量(编译报错:非法前向引用);
  • 变量即使只声明未赋值(如 static int y;),也在“准备阶段”被设为默认值(0 / null / false),但显式初始化动作仍按代码位置触发。

声明可见性 ≠ 执行时机

字段名在整个类体中都处于作用域内,所以静态块里可以提前给尚未声明的静态字段赋值(编译通过),但最终值由执行顺序决定:

  • 静态字段先被赋予默认值(如 int → 0);
  • 然后按源码顺序执行静态块和声明处赋值;
  • 后执行的语句会覆盖前面的赋值结果。

例如:static { a = 2; } 写在 static int a = 1; 前,a 最终是 1,不是 2。

立即学习“Java免费学习笔记(深入)”;

父子类之间强制分层执行

子类首次被主动使用时,JVM 保证父类静态部分全部完成后再执行子类静态部分:

  • 先执行父类中所有静态变量赋值 + 静态块(按父类源码顺序);
  • 再执行子类中所有静态变量赋值 + 静态块(按子类源码顺序);
  • 因此子类静态块可安全读取父类 public static 字段,但父类不能依赖子类静态变量。

异常会中断整个初始化流程

静态变量初始化或静态块中抛出未捕获异常(如 NullPointerException),会导致:

  • <clinit> 执行立即终止;
  • 该类进入“初始化失败”状态;
  • 后续任何访问(调用方法、new 实例、读字段)都会直接抛 NoClassDefFoundError
  • 不会重试,也不会执行其后未执行的静态代码。

热门栏目