静态代码块最先执行且仅一次,父类静态→子类静态;构造代码块每次new都执行,顺序为父块→父构→子块→子构;普通代码块仅随方法调用执行。

掌握静态代码块、构造代码块和构造方法的加载链条,关键在于理清“类加载”和“对象创建”两个阶段的触发时机与执行层级。它们不是并列关系,而是嵌套在 JVM 类初始化与实例化流程中的固定环节。
类加载阶段:静态代码块最先且只执行一次
当 JVM 第一次主动使用某个类(比如 new 实例、调用静态方法、访问静态字段),就会触发该类及其父类的加载与初始化。
- 先加载父类:执行父类的全部静态代码块(按书写顺序)
- 再加载子类:执行子类的全部静态代码块(按书写顺序)
- 静态代码块不能访问 this、非静态字段或方法,只能操作 static 成员
- 即使后续多次 new 对象,静态代码块也绝不再执行
对象创建阶段:构造代码块紧贴构造方法,每次 new 都走一遍
每次调用 new 创建实例时,JVM 会为该对象分配内存,并按固定顺序执行初始化逻辑——注意:构造代码块本质上被编译器“插入”到每个构造方法的最开头(在 super() 或 this() 调用之后)。
- 先执行父类构造代码块 → 再执行父类构造方法
- 再执行子类构造代码块 → 最后执行子类构造方法
- 构造代码块可访问实例变量、静态变量、实例方法和静态方法
- 多个构造方法共用同一组构造代码块,避免重复初始化逻辑
普通代码块:仅限方法内,随方法调用而执行
它不属于类或对象的生命周期管理环节,只是语法层面的局部作用域控制手段。
- 写在方法内部,用 {} 包裹
- 执行时机完全取决于所在方法何时被调用
- 主要用于限制变量生命周期或组织逻辑段,不影响类/对象初始化流程
验证链条的实用技巧
写一个带继承关系的最小测试类,输出带编号的日志,就能一目了然:
- 在父类和子类中分别定义 static{}、{} 和构造方法,都打印明确标识(如“父类静态”“子类代码块”)
- main 中 new 一次子类对象,观察输出顺序是否为:父静 → 子静 → 父块 → 父构 → 子块 → 子构
- 再 new 一次,确认静态部分不再出现,仅重复后四步
- 反编译 .class 文件,能看到构造代码块确实被合并进了构造方法字节码的起始位置










