静态代码块在类首次主动使用时执行且仅一次,构造函数每次new对象时运行并在静态和实例代码块之后;执行顺序为父类静态→子类静态→父类实例→父类构造→子类实例→子类构造。

静态代码块在类首次主动使用时执行,且仅一次;构造函数每次 new 对象时才运行,且总在静态代码块之后、实例代码块之后执行。关键不是“谁先写”,而是“谁属于哪个阶段”——静态属于类初始化,构造属于对象创建。
静态代码块的触发时机很明确
它不随类加载立即执行,而是在 JVM 执行「类初始化」阶段才运行,前提是该类被首次主动使用。常见触发场景包括:
- 第一次 new 某个类的实例
- 第一次调用该类的 public static 方法
- 第一次访问非编译期常量的 public static 字段(如 public static int PORT = 8080; 会触发,但 public static final int PORT = 8080; 不会)
- 反射调用 Class.forName("X")
多个静态代码块按源码从上到下顺序执行;若中途抛出未捕获异常,整个类进入初始化失败状态,后续所有对该类的主动使用都会直接抛 ExceptionInInitializerError。
构造函数永远晚于静态代码块和实例代码块
构造函数不是对象初始化的第一步。实际流程是:父类静态 → 子类静态 → 父类实例代码块 → 父类构造函数 → 子类实例代码块 → 子类构造函数。其中:
立即学习“Java免费学习笔记(深入)”;
- 实例代码块(即无 static 的 {} 块)会被编译器“复制”到每个构造函数开头,在 super() 或 this() 调用完成之后、构造函数方法体开始之前执行
- 构造函数本身只负责最终的、差异化的初始化逻辑,比如参数校验、资源分配、业务规则检查等
- 即使一个类有多个重载构造函数,所有构造函数都会先执行相同的实例代码块
字段初始化与代码块混合时的执行细节
当类中同时存在显式字段赋值、实例代码块和构造函数时,三者共同构成实例初始化流程,顺序固定:
- 字段直接赋值(如 private String name = "default";)和实例代码块交替执行,严格按源码声明顺序
- 例如:先声明字段并赋值 → 再遇到实例代码块 → 再声明另一字段并赋值 → 最后进入构造函数体
- 静态字段赋值与静态代码块同理,也按源码顺序交错执行,但全部发生在类初始化阶段
父子类之间的执行链条不可跳过
子类构造必然隐式或显式调用 super(),这决定了执行流必须先完成父类的完整初始化链:
- 父类静态部分(静态字段 + 静态代码块)→ 子类静态部分
- 父类实例部分(字段赋值 + 实例代码块)→ 父类构造函数
- 子类实例部分(字段赋值 + 实例代码块)→ 子类构造函数
- 任意一环缺失(如父类构造抛异常),后续环节全部中断


















