静态代码块在类首次主动使用时执行一次,构造代码块每次创建对象时在父类构造方法之后、本类构造方法之前执行;父子类初始化顺序为:父类静态块→子类静态块→父类构造块→父类构造器→子类构造块→子类构造器。

静态代码块在类首次被主动使用时执行一次,构造代码块在每次创建对象时、调用父类构造方法之后、本类构造方法体之前执行。
静态代码块只运行一次,且时机明确
它属于类初始化阶段,不是类一加载就立刻执行,而是等到第一次“主动使用”该类时才触发。常见主动使用包括:
- 调用该类的 public static 方法
- new 某个类的实例(哪怕只是 new 父类,也会触发父类静态块)
- 访问非编译期常量的 public static 字段(如 public static int PORT = 8080;但 public static final String MSG = "ok" 不会触发)
- 通过反射调用 Class.forName("X")
多个静态代码块按源码从上到下顺序执行。一旦抛出未捕获异常,整个类初始化失败,后续再使用该类会直接报 ExceptionInInitializerError。
构造代码块每次 new 都执行,位置固定
它不依赖类加载,而是对象初始化的一部分。JVM 会在每个构造器中自动把它“插入”到如下位置:
立即学习“Java免费学习笔记(深入)”;
- 父类构造器已通过 super() 完成调用之后
- 本类构造方法体开始之前
因此无论有多少个重载构造器,只要被调用,该块就执行一次。它可以访问静态成员和已声明的实例成员,适合抽取多个构造器共有的初始化逻辑。
父子类完整执行顺序是严格分阶段的
执行 new Child() 时,实际流程分两阶段:
- 类初始化阶段(仅首次):父类静态代码块 → 子类静态代码块
- 对象实例化阶段(每次 new):父类构造代码块 → 父类构造方法 → 子类构造代码块 → 子类构造方法
注意:静态块全程只执行一次;之后每次 new 都重复后四步。若父类构造器中调用了可被子类重写的方法,此时子类字段尚未初始化(因子类构造块还没执行),容易引发空指针或非法前向引用问题。
普通方法里的 {} 不参与初始化流程
写在方法内部的 {}(例如 void foo() { int x = 1; { System.out.println(x); } })只是语法作用域结构,与类加载或对象创建无关。它的执行完全取决于方法是否被调用、执行流是否到达该位置——即使类从未初始化,只要方法被调用且走到此处,它就会运行。


















