Java中引用类型参数传递的是对象地址的副本,而非引用本身;因形参与实参是独立栈变量,仅地址值相同,故可共享堆对象状态修改,但重赋值互不影响。

Java中引用类型对象作为方法参数传递时,传递的是该对象引用(即内存地址)的一个副本,不是对象本身,也不是引用本身,而是引用值的拷贝。
为什么说是“地址副本”而不是“引用本身”
每个引用变量在栈中存储一个值——这个值是堆中对象的内存地址。传参时,JVM把这个地址值复制一份,放进方法的栈帧里。原始变量和形参是两个独立的栈变量,只是它们当前存的地址相同,因此指向同一个堆对象。
- 修改对象属性(如
obj.name = "Alice"或list.add(1))会影响原对象——因为操作的是同一块堆内存 - 让形参指向新对象(如
obj = new Person())只改变副本的指向,原始变量仍指向旧对象 - 这就像把一把钥匙复制了一把交给别人:两人能开同一个抽屉,但各自换钥匙互不影响
常见误解澄清
很多人看到“改属性生效”就误以为是引用传递,其实关键在操作目标:
-
String是引用类型,但方法内写str = "new"不影响外部——因为字符串不可变,实际是新建对象并让形参副本指向它 -
Integer i = 5传入后执行i++,外部不变——自动装箱产生新对象,形参副本换了地址 - 数组也是引用类型:
arr[0] = 99生效(改堆内容),arr = new int[3]无效(只改副本指向)
与基本类型的对比更清晰
二者都是值传递,区别仅在于“复制的内容”不同:
立即学习“Java免费学习笔记(深入)”;
- 基本类型(
int、boolean等):复制栈中数值本身,方法内修改完全隔离 - 引用类型(类、接口、数组等):复制栈中存储的地址值,地址一致 → 操作同一堆对象
多态和灵活性的底层支撑
正因为传的是地址副本,父类形参才能接收任意子类实参:
-
void handle(Animal a)可传Cat或Dog实例 - 运行时根据实际对象类型决定调用哪个
show()方法 - 这种设计不依赖引用是否被替换,只依赖地址指向的对象真实类型


















