引用类型变量存储的是堆中对象的地址而非数据本身。变量在栈中存地址,对象在堆中存实际内容;赋值和传参均复制地址,导致多变量可共享同一对象,修改属性会影响所有引用,但重新赋值仅改变局部指向。

引用类型变量本身不存数据,只存地址——这个地址指向堆内存中真正的对象。理解这一点,就抓住了引用类型行为的核心。
变量在栈中,对象在堆中
声明一个引用类型变量(比如 Person p = new Person();),JVM 会在栈中创建一个名为 p 的空间,里面只放一个“门牌号”;真正的 Person 对象(含所有字段)则完整地存在堆内存里。这个“门牌号”就是对象的内存地址。
- 栈里的变量生命周期短,随方法调用结束而释放
- 堆里的对象生命周期长,靠垃圾回收器判断是否还被引用
- 哪怕对象里有字符串、数组等其他引用类型字段,这些字段的“地址值”也和对象一起存在堆中
赋值=复制地址,不是复制对象
当你写 Person p2 = p1;,不是把整个 p1 对象拷了一份,而是把 p1 存的那个地址原样抄给 p2。结果是两个变量指向同一块堆内存。
- 修改 p1.name = "Alice",p2.name 也会变成 "Alice"
- 修改 p1.age = 30,p2.age 同步变化
- 但重新赋值 p1 = new Person();,只会改变 p1 的指向,p2 仍指向原来的对象
成员变量全在堆里,不分基本还是引用
类里的字段——无论是 int age 还是 String name 或 User boss——都作为对象的一部分,统一存放在堆中。
- age 的数值直接存在对象内存块里
- name 字段存的是一个地址(指向另一个堆中的字符串对象,或字符串常量池里的引用)
- 没有哪个成员变量会跑到栈里去,哪怕是 boolean 或 char
方法参数传递也是传地址副本
把引用类型变量传进方法,形参拿到的是实参地址的一个拷贝,不是对象本身,也不是原始变量的别名。
- 在方法内修改对象属性(如 user.setName("Bob")),会影响原对象
- 但在方法内让形参指向新对象(如 user = new User();),不会影响实参的指向
- 本质是:你拿到了钥匙的复印件,能开同一扇门;但换一把新钥匙,不影响别人手里的那把

















