java中代码块执行顺序由jvm严格按规范控制:静态部分在类首次主动使用时执行一次,顺序为父类静态变量→父类静态块→子类静态变量→子类静态块;实例部分每次new时执行,顺序为父类字段默认值→显式赋值与构造块→构造器→子类同理。

Java 中代码块执行顺序不是靠“计算”得出的,而是由 JVM 严格遵循语言规范在类加载和对象创建两个阶段自动控制的。你不需要手动算,但必须清楚每个代码块在哪个阶段、按什么规则触发。
静态代码块和静态变量初始化:只在类首次主动使用时执行一次
- 触发时机:第一次 new、调用静态方法、访问非 final 静态字段等
- 执行顺序:父类静态变量(按声明顺序)→ 父类静态代码块(按书写顺序)→ 子类静态变量 → 子类静态代码块
- 关键点:
- 整个过程封装在
<clinit></clinit>方法中,JVM 保证只执行一次 - 若任一静态块抛出未捕获异常,类初始化失败,后续所有访问都抛
ExceptionInInitializerError -
public static final String MSG = "ok";这类编译期常量不触发类初始化
- 整个过程封装在
实例代码块、字段显式初始化、构造器:每次 new 对象时执行一遍
- 触发时机:每次调用
new创建实例时 - 执行顺序(完整链):
- 父类字段默认值(如
int x→0,Object o→null) - 父类实例变量显式赋值(如
String name = "Tom";)和构造代码块({ ... }),按源码从上到下合并执行 - 父类构造器体(含隐式或显式
super()) - 子类字段默认值
- 子类实例变量显式赋值和构造代码块,同样按源码顺序执行
- 子类构造器体
- 父类字段默认值(如
- 关键点:
- 构造代码块被编译器自动插入到每个构造器开头(
super()返回后、构造体之前) - 字段赋值语句和构造代码块地位等同,混写时顺序即执行顺序
- 父类构造器中若调用被子类重写的方法,此时子类字段尚未初始化,仍为默认值
- 构造代码块被编译器自动插入到每个构造器开头(
局部代码块:完全跟随方法执行流,与初始化无关
- 写在方法内部的
{ ... },无论是否嵌套在 if/for/try 中,都只是作用域语法 - 执行时机:方法被调用,且执行流到达该大括号时
- 变量在块内声明,出块即销毁,不参与任何类或对象生命周期
- 常用于临时计算、资源提前释放(如手动 close 流)、避免变量名冲突
验证执行顺序最可靠的方式是打日志
- 在静态块里输出
[S] Parent,实例块里输出[I] Parent,构造器第一行输出[C] Parent() - 连续
new Child()两次,观察输出:第一次含全部[S]和[I]/[C],第二次只有[I]/[C] - 乱序或缺失,通常意味着类加载被跳过(如只用了
static final基本类型)、异常中断,或this()调用干扰了构造链
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











