静态代码块最先执行且仅一次,在类初始化阶段;实例代码块每次创建对象时执行,位于构造器体之前;局部代码块仅在所在方法被调用且执行流到达时运行。

静态代码块先执行,父类优先且只一次
类加载时就触发静态代码块,和创建对象无关。JVM 加载子类前,必须先把父类完整初始化——包括父类静态变量赋值、静态代码块,全部按源码顺序跑完,才轮到子类的静态部分。哪怕你只写 new Child(),也会顺带把 Parent.class 加载并初始化一遍。之后再 new 多少次 Child,静态代码块都不会重跑。
实例代码块每次 new 都执行,严格按继承链展开
每次调用 new 创建对象,才会进入实例初始化阶段。这个过程是递进式的:先给父类分配内存、设默认值,再执行父类的实例代码块(即普通 {} 块)、然后跑父类构造器;等父类构造结束,才开始子类的实例代码块和构造器。注意,实例代码块总在对应构造器体的第一行隐式插入,哪怕你没写 super(),编译器也自动加了。
字段初始化嵌在代码块流程里,顺序不能错
实例变量显式赋值(比如 String s = init();)和实例代码块是混在一起执行的,都发生在构造器体之前,且严格按源码声明顺序。如果 init() 方法里有日志,就能看到它出现在“父类实例代码块”之后、“父类构造器体第一行”之前。同理,静态变量赋值也穿插在静态代码块中,按书写顺序依次执行。
调试时用带标识的日志锚定每个环节
别靠记忆猜顺序,直接在关键位置打日志:
- 每个静态代码块开头加 [S] Parent
- 每个实例代码块开头加 [I] Parent
- 每个构造器第一行加 [C] Parent()
- 字段初始化方法内部也加日志,比如 init() → [F] Parent.init
观察输出是否稳定符合 S-P → S-C → I-P → C-P → I-C → C-C 模式。一旦乱序,大概率是静态依赖循环、this() 调用干扰,或者某个 init() 抛了异常中断了流程。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











