父类构造块一定在子类构造块之前执行,顺序为:父类普通代码块→父类构造方法→子类普通代码块→子类构造方法,全程单向、不可跳过、不可并发,成员变量初始化被编译器插入对应类普通代码块位置,在构造方法前执行。

父类构造块(即非静态代码块)一定在子类构造块之前执行,且整个顺序是单向、不可跳过、不可并发的。
父类构造块先于子类构造块执行
每次 new 一个子类对象时,JVM 会严格按以下顺序填充实例:
- 父类普通代码块(含父类成员变量显式初始化)
- 父类构造方法
- 子类普通代码块(含子类成员变量显式初始化)
- 子类构造方法
注意:成员变量声明处的初始化(如 String name = "Alice";)会被编译器自动“挪”到对应类的普通代码块中,在构造方法调用前执行,但仍在父类初始化完成之后才轮到子类部分。
构造块与构造方法不是独立环节,而是嵌套在初始化链里
普通代码块不是可选补充,而是 JVM 实例化流程的固定环节。它和字段初始化共同构成“实例初始化阶段”,位置固定在构造方法调用之前。比如:
立即学习“Java免费学习笔记(深入)”;
- 父类中写 { System.out.println("A init"); } → 在父类构造方法前打印
- 子类中写 { System.out.println("B init"); } → 在子类构造方法前打印,但一定在父类全部初始化之后
这种顺序保障了子类能安全访问已初始化的父类状态,也避免了子类字段被父类方法误读为默认值(如 null 或 0)。
别混淆静态块和构造块的触发时机
静态代码块属于类加载阶段,只执行一次;而构造块属于对象创建阶段,每次 new 都走一遍。二者层级不同:
- 类首次使用时:父类静态块 → 子类静态块(仅一次)
- 每次 new 时:父类构造块 → 父类构造方法 → 子类构造块 → 子类构造方法
如果在 main 中先 new 父类再 new 子类,静态块只在第一次类加载时运行,后续 new 不再触发静态块,但构造块每次都会执行。
super() 必须在第一行,本质是守住这条流水线起点
子类构造方法首行隐式或显式调用 super(),不是语法限制,而是机制需要:确保父类构造块和构造方法已完整执行,子类字段才开始初始化。若允许中间插入逻辑,就可能在父类尚未就绪时,调用子类重写的方法——此时子类字段仍是默认值,极易引发 NullPointerException 或逻辑错误。


















