Java中所有赋值和参数传递都是值传递,引用类型传递的是对象地址的副本;地址相同导致共享对象状态修改可见,但变量间无绑定关系,重新赋值互不影响。

Java里根本不存在真正的引用传递,所谓“引用类型赋值像引用传递”,只是对内存行为的直观误解。关键在于:赋值操作本身永远是值传递——只不过传递的是“引用地址的值”,不是对象本身,也不是引用变量本身。
引用类型变量存的是地址,不是对象
声明一个引用类型变量(比如 User u = new User()),栈中只存一个4字节或8字节的地址值,指向堆中那个实际对象。这个地址值本身是可复制、可覆盖的原始数据。
- u = v 不是把“v这个变量”传过去,而是把 v 当前持有的地址值复制给 u
- 之后 u 和 v 指向同一对象,是因为它们存储了相同的地址,不是因为“绑定了同一个变量”
- 若后续执行 v = new User(),v 的地址值被更新,u 不受影响
赋值 ≠ 绑定,更不等于别名
很多人误以为 String s = "abc"; String t = s; 让 t 成为 s 的别名,其实不是。s 和 t 是两个独立的栈变量,各自持有相同地址值。它们之间没有运行时联动关系。
- 修改 t 的引用目标(如 t = "xyz")只会改 t 自己的地址值
- s 仍指向原字符串对象,不会同步变化
- 这和 C++ 中 int& r = x 这种真正绑定变量生命周期的引用有本质区别
为什么看起来像“引用传递”?
因为多个变量持有同一地址,通过任一变量调用方法修改对象内部状态(如 user.setName("Tom")),所有持有该地址的变量再去读取时,看到的都是更新后的结果——但这不是传递方式导致的,而是共享同一堆对象的结果。
- 方法参数接收的仍是地址副本(值传递),但副本和原地址指向同一块堆内存
- 所以方法内通过该副本修改对象属性,外部能感知;但若在方法内让形参指向新对象(user = new User()),外部实参不受影响
- 这种“一半可见、一半隔离”的行为,正是混淆的根源
一句话厘清
Java 所有赋值和参数传递,都是值传递;引用类型的“值”,恰好是对象在堆中的地址。地址被复制,不代表对象被复制,也不代表变量被绑定——它只是个数字,一个可以拷贝、比较、重写的普通值。

















