new 的核心作用是分配内存而非调用构造器:先在堆中划出空间并零值初始化(int=0、引用=null),再执行构造方法;其四步流程为类加载检查→堆内存分配→零值初始化与对象头设置→调用方法。

new 不是调用构造器,而是先分配内存、再触发构造器。很多人误以为 new 的作用就是“执行构造方法”,其实它真正干的第一件事,是在堆中划出一块干净的内存空间——此时对象字段已按类型默认初始化(int=0、引用=null),但构造器一行代码都还没跑。
new 的四步内存动作不可跳过
每次 new 执行,JVM 严格按顺序完成:
- 类加载检查:确认类已加载并完成初始化(静态块已执行、static 字段已赋值)
- 堆内存分配:在 Eden 区(通常走 TLAB 线程私有缓冲),按对象大小划出连续空间
- 零值初始化:把整块内存清零,设置对象头(含 Klass 指针和 Mark Word)
- 调用
方法:才真正开始执行你写的构造器逻辑,包括 this() 调用、字段显式赋值、父类构造链等
构造器不负责“创建”,只负责“初始化”
构造器本质是普通实例方法(签名固定为
- 给字段赋业务初始值(覆盖默认值)
- 校验参数合法性(如 throw new IllegalArgumentException)
- 调用父类构造器(隐式或显式 super())
- 执行 this(...) 链式调用(必须放在首行)
注意:如果构造器抛异常,对象内存已分配且零值已设,但引用变量仍为 null(或未赋值),不会自动释放——这块内存等 GC 回收。
绑定发生在栈与堆之间,不是“绑定构造器”
所谓“new 绑定”,实际是指栈中引用变量与堆中对象地址的关联:
- new 返回的是堆内存首地址,这个地址被存入栈帧的局部变量表(比如 Person p = new Person() 中的 p)
- 后续所有 p.name、p.sleep() 都靠这个地址去堆里找数据或方法表
- 构造器内 this 就是这个地址的别名,所以 this.name 和 name 在无重名时等价
不存在“构造器绑定”这种说法——构造器只是被 new 调用的一段初始化代码,它不持有、也不管理引用关系。
容易踩坑的三个典型场景
- 忘了 new 却调用方法:引用为 null,触发 NullPointerException;根源常是条件分支漏写 new 或工厂方法返回 null
- 继承中字段初始化顺序错乱:父类构造器先跑,但子类字段内存已在 new 时一并分配并置零;若父类构造器调用被子类重写的方法,可能访问到未初始化的子类字段(值为默认值)
- 误信字符串/Integer 的“免 new”假象:"abc" 或 Integer.valueOf(100) 看似没 new,实则底层仍可能 new(缓存未命中时)或复用已有对象;它们不改变 new 的语义,只是 JVM 的优化策略











