Java中多层嵌套对象传参本质仍是值传递,传递的是对象引用地址的副本;无论嵌套几层,每次赋值或传参都只复制一次地址值,修改嵌套属性之所以对外可见,是因为所有地址副本指向同一堆内存区域。

Java 中多层嵌套对象传参,本质仍是值传递——但传的“值”是对象引用的副本,不是对象本身,更不是引用的引用。理解它,关键不在“嵌套几层”,而在于每一层的变量如何持有和传递地址。
嵌套对象的参数本质:地址的副本再副本
比如有 User 类包含 Address 字段,Address 又包含 City 字段:
- User u = new User(); → u 是一个引用变量,存的是堆中 User 对象的地址
- u.getAddress() 返回一个 Address 引用 → 这个返回值仍是地址(Address 对象在堆中的位置)
- 把这个返回值作为参数传给方法,传的不是 Address 对象,而是这个地址值的一份拷贝
也就是说,“嵌套”只是访问路径变长了,底层每次赋值、每次传参,都只复制一次地址值。不存在“传到第三层就变成引用传递”的情况。
修改嵌套属性时为什么外部可见?
因为所有副本指向的是同一个堆内存区域。例如:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
立即学习“Java免费学习笔记(深入)”;
- 方法内执行 addr.setCity("Beijing"); → 实际是通过地址找到堆里的 Address 对象,改它的 city 字段
- 调用方的 u.getAddress() 拿到的还是原来那个地址,所以读到的 city 也变了
- 这和你用两把相同的钥匙打开同一扇门,谁在里面改了摆设,另一个人开门后也能看见
什么时候修改不会影响外部?
只要切断了“地址副本 → 原对象”的路径,外部就感知不到。常见情形包括:
- 在方法里重新 new 一个新对象并赋给形参变量:addr = new Address(); → 形参 addr 现在指向新地址,原 u.address 不受影响
- 对嵌套字段本身做重新赋值(而非修改其内容):addr = null; 或 addr.setCity = null; → 前者断开引用,后者只改字段值,不影响外层结构
- 传入的是 getter 返回的新对象(如返回 new Address() 而非原始引用),那从一开始就是独立副本
实战中容易踩的坑
多层嵌套常让人误以为“越深越难控制”,其实风险点很集中:
- DTO/VO 层级过深(如 User → Profile → Preferences → Theme → Color),但 DAO 层直接接收并修改它 → 外部状态被意外污染
- 方法签名接受 User,却在内部调用 user.getAddress().setZipcode(...),导致调用方未预期的副作用
- 用 BeanUtils.copyProperties 浅拷贝嵌套对象,结果 copy 后的 address 仍和原对象共享同一 Address 实例
规避方式很简单:需要隔离就深拷贝,需要协作就明确契约,别依赖“它应该不会改我这个”。

















