java对象初始化分“类初始化”和“对象初始化”两阶段:类初始化只执行一次,按源码顺序执行静态变量赋值和静态代码块,父类优先;对象初始化每次new都触发,先父类后子类,依次执行实例变量赋值、构造代码块、构造方法。

Java 对象初始化不是一气呵成的操作,而是由「类初始化」和「对象初始化」两个阶段构成,彼此独立又严格依赖——类初始化必须先完成,对象初始化才能开始。
类初始化:只执行一次,决定静态成员命运
当类首次被主动使用(比如调用 static 方法、访问 static 字段、或执行 new),JVM 启动类初始化流程。这个过程全局唯一,与具体对象无关:
- 为所有静态变量分配内存,并设默认值(int → 0,引用类型 → null,boolean → false)
- 按源码中声明顺序,依次执行静态变量显式赋值语句和静态代码块(二者同级,谁在前谁先跑)
- static final 编译期常量(如 static final int X = 1;)不参与运行时初始化,直接内联到调用处
- 父类静态部分一定先于子类执行;若有继承关系,顺序是:父类静态变量 → 父类静态代码块 → 子类静态变量 → 子类静态代码块
对象初始化:每次 new 都触发,填充每个实例的专属状态
类初始化完成后,每执行一次 new,就启动一次对象初始化。它发生在堆内存分配之后、构造方法执行之前,顺序固定不可跳过:
- 为所有实例变量分配内存,并设默认值(int → 0,引用 → null)
- 按源码中出现顺序,依次执行父类的实例变量赋值、实例代码块(即非 static 的 {...})
- 调用父类构造方法(即使没写 super(),编译器也会自动插入)
- 再按源码顺序,执行子类的实例变量赋值、实例代码块
- 最后执行子类构造方法体——此时所有实例成员已就绪,可安全访问
关键细节与常见误区
这些点容易出错,需特别注意:
- new 指令 ≠ 初始化完成:new 先分配内存并零值填充,再走初始化流程;若构造方法中抛异常,对象内存已分配但未构建成功
- 静态上下文不能访问非静态成员:静态方法/块运行时,实例部分根本不存在,编译直接报错
- 局部变量无默认值:必须显式初始化才能使用,编译器强制检查;这和成员变量行为完全不同
- 类加载 ≠ 类初始化:加载(读字节码)、链接(验证/准备/解析)可能早于初始化;只有首次“主动使用”才触发初始化
底层七步执行链(JVM 标准视角)
每次 new 一个对象,JVM 底层严格走完以下七步:
- 类加载:加载、验证、准备、解析
- 静态变量默认初始化(0 / null / false)
- 静态显式赋值 + 静态代码块(从上到下)
- 实例变量默认初始化(新建内存,全部赋默认值)
- 实例变量显式赋值 + 实例代码块(从上到下)
- 构造方法执行
- 对象创建完成,引用指向堆内存
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











