静态代码块先执行,顺序为:静态代码块 → 构造代码块 → 构造函数;静态代码块在类加载时执行且仅一次,构造代码块在每次创建对象时、构造函数前执行。

静态代码块和构造代码块谁先执行
静态代码块在类加载时就执行,且只执行一次;构造代码块在每次创建对象时执行,在构造函数之前。所以顺序永远是:静态代码块 → 构造代码块 → 构造函数。
多个静态代码块的执行顺序
按它们在类中出现的**从上到下顺序**执行。编译器不会合并或重排,哪怕中间隔着字段或方法声明。
- 如果类 A 继承类 B,那么先执行父类 B 的所有静态代码块,再执行子类 A 的
- 静态代码块里不能访问非静态成员(比如
this、普通字段),否则编译报错:non-static variable xxx cannot be referenced from a static context - 即使你从没 new 过这个类,只要它被主动加载(比如通过
Class.forName("X")或首次访问其静态成员),静态代码块就会触发
构造代码块和构造函数的配合细节
构造代码块本质是“插队进每个构造函数开头”的逻辑,编译后会被复制到每个构造函数的第一行(在 super() 或 this() 调用之后)。
- 如果你写了
public X() { this(1); }和public X(int i) { ... },那构造代码块只在X(int)里生效一次,不会在X()中重复执行 - 构造代码块里可以访问
this和所有实例字段,但要注意:字段初始化语句(如int x = 5;)其实也等效于放在构造代码块里,顺序按源码位置算 - 别在构造代码块里调用可能被子类重写的方法(
overridden method),此时子类字段可能还没初始化,容易 NPE
常见误判场景:继承 + 多级初始化
最容易搞混的是「父类静态 → 子类静态 → 父类构造代码块 → 父类构造函数 → 子类构造代码块 → 子类构造函数」这个链条。只要记住两个铁律:
立即学习“Java免费学习笔记(深入)”;
- 所有
static相关内容(字段、代码块、静态内部类)都在类加载阶段完成,与对象无关 - 非 static 初始化(构造代码块、字段赋值、构造函数)属于「实例化过程」,严格按继承链从父到子、每层内按代码顺序走
- 如果子类构造函数第一行是
super(...),那父类的构造代码块一定在子类的之前;如果是this(...),则当前类的构造代码块会先执行一轮,再跳转——这点常被忽略
真正麻烦的地方不在规则本身,而在调试时看不到构造代码块的调用栈痕迹。它不生成独立方法,也不出现在 javap -c 的字节码方法列表里,只藏在每个构造函数的指令流开头。想确认执行时机,加日志比断点更靠谱。










