成员变量初始化发生在内存分配后、构造器执行前,按默认值→显式赋值→构造器的固定时序进行,且严格遵循父子类继承链和声明顺序。

成员变量的初始值是在对象构建过程中早于构造器执行、但晚于内存分配的关键环节,它发生在 new 操作触发的堆内存初始化阶段,属于对象创建流程中不可跳过的固定步骤。
默认值在堆内存分配时就写入
当你执行 new Person() 时,JVM 首先为对象在堆上分配内存空间,紧接着立即对所有实例成员变量进行默认初始化:int 变成 0,boolean 是 false,引用类型一律设为 null。这个动作由 JVM 自动完成,不依赖任何 Java 代码,也不经过构造器。
- 局部变量没有这一步——未显式赋值就用,编译直接报错
- final 实例变量虽有默认值(如 0 或 null),但必须在构造器结束前被明确赋值,否则编译失败
- 静态变量的默认初始化发生在类加载时,与单个对象无关
定义时显式赋值紧随其后
默认值写入之后,JVM 按照源码中成员变量声明的从上到下顺序,逐个执行定义处的显式赋值(如 String name = "Tom"; 或 int age = calcAge();)。这步发生在父类构造器调用返回之后、子类构造器主体代码开始之前。
- 若某字段既定义时赋值,又在构造器里再赋值,后者会覆盖前者
- 赋值表达式中调用的方法若被子类重写,此时子类字段仍为默认值,容易引发逻辑异常
- 后面声明的变量可以使用前面已赋值的变量(如
int x = 5; int y = x * 2;),但反向依赖会编译报错
构造器是最后一步,不是起点
很多人误以为“构造器负责初始化成员变量”,其实构造器只是初始化流程的终点——它运行时,成员变量早已完成默认初始化和定义时赋值。构造器的作用是二次赋值、条件控制、参数绑定或资源获取,比如根据传入参数决定状态,或调用外部服务填充字段。
- 无参构造器可能只做日志或校验,不改动已有值
- 全参构造器常用于覆盖定义时的固定值,实现差异化对象状态
- Builder 模式本质上把构造器逻辑拆解,但仍遵守相同初始化时序
父子类中的初始化链条
继承场景下,初始化严格按层级推进:先父类静态 → 父类实例变量默认值 → 父类定义时赋值 → 父类构造器 → 子类实例变量默认值 → 子类定义时赋值 → 子类构造器。子类构造器第一行隐式或显式调用 super(),正是为了确保父类部分先就绪。
- 不能在
super()调用中传递未初始化的子类实例字段(编译拒绝) - 子类字段的默认值已在父类构造器执行期间存在,只是尚未被显式赋值
- 构造代码块({})的执行时机夹在定义时赋值和构造器之间,也遵循声明顺序

















