根本原因在于内存存储与赋值机制不同:基本类型在栈中直接存值,赋值为值拷贝;引用类型在栈中存堆地址,赋值为地址拷贝,故修改对象状态时多个引用联动。

Java变量赋值时,基本类型和引用类型的行为完全不同——根本原因在于它们在内存中如何存放数据、如何复制以及后续修改是否产生联动。
栈中存值 vs 栈中存地址
基本类型(如 int、boolean、char)的变量值直接存在栈内存里。声明 int a = 5,数字 5 就实实在在放在栈上一个固定大小的空间中。
引用类型(如 String、ArrayList、自定义类对象)的变量本身也存在栈上,但它存的不是数据,而是一个“地址”,指向堆内存中真正对象所在的位置。比如 String s = new String("hi"),栈里的 s 存的是堆里那个字符串对象的地址,内容“hi”实际在堆中。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
赋值即拷贝:值拷贝 vs 地址拷贝
赋值操作不是“建立连接”,而是“复制一份”。但复制的内容不同:
- 基本类型赋值是值拷贝:两个变量各自拥有独立副本,互不干扰
例如:int x = 10; int y = x;→ 修改y = 20,x仍是 10 - 引用类型赋值是地址拷贝:两个变量拿到的是同一个地址,因此指向同一块堆内存
例如:StringBuilder sb1 = new StringBuilder("a"); StringBuilder sb2 = sb1;→ 执行sb2.append("b")后,sb1.toString()也会变成 "ab"
修改影响范围:独立 vs 共享
是否影响其他变量,取决于你改的是什么:
- 对基本类型变量重新赋值(如
a = 100),只改自己,不影响别人 - 对引用类型变量重新赋值(如
s = "new"),只是让该变量指向新地址,不影响原来指向的对象,也不影响其他引用它的变量 - 但若通过引用修改对象内部状态(如调用
list.add()、arr[0] = 99),只要多个变量指向同一对象,所有引用都会看到变化
常见误区提醒
容易混淆的点往往出现在字符串和包装类上:
- String 是引用类型,但不可变——每次“修改”其实是创建新对象,原引用不变,所以看起来像值类型行为,本质仍是地址拷贝+新建对象
-
Integer、Boolean 等包装类也是引用类型,默认可为
null;但自动装箱时小范围数值(-128~127)会复用缓存对象,导致==偶尔“碰巧”返回 true,这不代表它们是基本类型 - 数组是引用类型:
int[] a = {1,2}; int[] b = a;→b[0] = 99会让a[0]也变成 99
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










