静态代码块总是在最前,因为它属于类初始化阶段,由JVM在类首次主动使用时严格保证执行,且仅一次;其顺序为父类静态成员、子类静态成员,不受书写顺序影响。

静态代码块总是在最前,是因为它绑定在类的「初始化阶段」,而这个阶段发生在任何对象创建之前,且由 JVM 严格保证——只要类被首次主动使用,就立即触发,不依赖 new、不等待 main,也不受父子类实例化顺序干扰。
静态块为什么能抢在一切之前
它不属于对象,而属于类本身。JVM 加载类后,进入「类初始化」阶段(Initialization),此时才执行 static {}。这个阶段的触发条件包括:
- 第一次 new 某个类的实例
- 第一次调用该类的 public static 方法
- 第一次访问非编译期常量的 public static 字段(如 public static int PORT = 8080;)
- 反射调用 Class.forName("X")
注意:类“加载”(Loading)不等于“初始化”,static 块只在初始化阶段跑,且仅一次。
父子类中静态块的真实顺序
子类被主动使用时,JVM 会先确保父类已完成初始化。所以顺序固定为:
立即学习“Java免费学习笔记(深入)”;
- 父类静态变量赋值 & 父类静态代码块(按源码顺序)
- 子类静态变量赋值 & 子类静态代码块(按源码顺序)
哪怕子类静态块写在父类前面,JVM 也会先加载并初始化父类——这是继承契约的底层保障,不是代码书写顺序决定的。
一个容易踩坑的特例:静态字段初始化含 new
如果静态变量本身是 new 出来的对象,比如:
public static Parent p = new Parent();
那么执行流程会变成:
- 开始初始化 Parent 类 → 触发 Parent 静态块?不,还没到那步
- 先执行 p = new Parent() → 进入 Parent 实例化流程
- 于是先跑 Parent 的实例代码块、再跑 Parent 构造方法
- 等 Parent 初始化完,才继续执行 Parent 类里定义在它之后的静态代码块
也就是说:静态字段的赋值表达式,会打断静态块的“连贯执行”,但整个类的初始化仍只发生一次。
普通块和构造块根本不参与这场“抢跑”
构造代码块({})属于对象初始化环节,每次 new 才执行,位置在 super() 返回之后、构造方法体之前;普通块(方法内的 {})只是作用域语法糖,完全不介入类或对象生命周期。它们和静态块不在同一个维度上竞争——一个管“类诞生”,另两个管“对象出生”。


















