java只有值传递:基本类型传数值副本,引用类型传地址副本;二者均不改变原变量本身,但引用副本可修改堆中对象状态。

Java 中没有真正的“引用传递”,只有“值传递”——但这个“值”,对对象来说,是堆内存中的地址。
理解这一点,就抓住了核心。
对象引用的值传递本质
- 你声明
Person p = new Person("Alice"),变量p本身存在栈中,它存储的不是对象,而是一个指向堆中Person实例的地址(比如0x7f8a12); - 调用
modify(p)时,JVM 把p的这个地址值复制一份传给形参person,person也在栈中,也存着0x7f8a12; - 此时
p和person是两个独立的栈变量,但它们的值相同,都指向堆中同一个对象; - 所以
person.name = "Bob"实际是通过地址找到堆里的对象并改它的字段——外部p.name自然变成"Bob"; - 但如果在方法里写
person = new Person("Charlie"),只是让person这个栈变量指向新地址,p完全不受影响。
为什么 String 看似“没变”
-
String str = "hello",str指向常量池或堆中一个不可变字符串对象; - 方法里
str = "world",本质是让形参str指向另一个新字符串对象; - 原来的
str变量仍指向"hello",所以外部看不到变化; - 这不是“传递方式不同”,而是
String类设计为不可变 + 重新赋值改变了引用指向。
数组和集合也是同理
-
int[] arr = {1, 2},传入方法后,形参数组变量也持有一份地址; -
arr[0] = 99→ 修改堆中数组内容,外部可见; -
arr = new int[]{3, 4}→ 仅改变形参指向,原arr不受影响; -
ArrayList<string> list</string>同样:list.add("x")有效,list = new ArrayList()无效。
关键判断口诀
- 能否影响外部对象状态?→ 看是否通过地址修改了堆中数据;
- 能否改变外部变量指向?→ 不能,形参重赋值只作用于自己;
- 所有“看起来像引用传递”的行为,都源于共享堆地址,而非共享变量单元。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











