Java对象初始化分“类加载”和“对象创建”两阶段:类加载时执行静态变量赋值和静态代码块(仅一次),对象创建时执行实例变量赋值、实例代码块和构造器(每次new都执行);继承下严格按父类静态→子类静态→父类实例→子类实例顺序执行。

Java中对象初始化不是简单地调用构造器,而是涉及静态变量、静态代码块、实例变量、实例代码块和构造器的多阶段协作。关键在于理解“类加载”和“对象创建”两个生命周期的分离,以及它们各自触发的内容。
单个类的初始化顺序
当首次使用某个类(如第一次 new 或访问其静态成员)时,JVM完成类加载,此时执行:
- 按声明顺序初始化所有静态变量(含赋值表达式)
- 按出现顺序执行所有静态代码块
之后每次 new 对象时,才进入对象创建阶段,依次执行:
- 按声明顺序初始化所有实例变量
- 按出现顺序执行所有实例代码块
- 最后调用对应的构造器
注意:静态部分只执行一次;实例部分每次 new 都完整走一遍。
立即学习“Java免费学习笔记(深入)”;
继承场景下的完整链条
子类对象初始化会触发父类与子类的协同加载,顺序严格分层:
- 父类静态变量 → 父类静态代码块(同级按书写顺序)
- 子类静态变量 → 子类静态代码块
- 父类实例变量 → 父类实例代码块 → 父类构造器
- 子类实例变量 → 子类实例代码块 → 子类构造器
这个顺序不可跳跃或倒置。即使子类静态代码块写在父类前面,它也一定在父类静态内容之后执行——因为JVM必须先确保父类已加载完毕,才能加载子类。
代码块的实际价值与使用建议
静态代码块适合做全局一次性准备,比如数据库连接池初始化、配置加载、日志框架启动等;实例代码块则用于多个构造器共用的初始化逻辑,避免重复代码。
- 静态代码块不能访问 this、非静态字段或方法,只能操作静态成员
- 实例代码块可访问全部成员(包括 this),但不能有返回值或参数
- 若某字段既被实例变量直接赋值,又被实例代码块修改,后者生效(因代码块在变量初始化之后执行)
例如:private String name = "default"; { name = "init-block"; },最终 name 值为 "init-block"。
调试与验证技巧
快速确认执行顺序,最有效的方式是打印带类名和阶段标识的日志:
- 在每个静态代码块里写 System.out.println("A - static block");
- 在每个实例代码块里写 System.out.println("A - instance block");
- 在每个构造器第一行写 System.out.println("A - constructor");
运行 new 子类对象后,输出将清晰映射出整个初始化流程,比查文档更直观可靠。


















