引用数据类型变量存储的是对象内存地址而非实际值,如String、ArrayList等;赋值或传参时复制的是地址,故修改对象内容会影响原对象,但重新赋值地址则不影响。

引用数据类型就是存地址,不是存值
Java里所谓“引用数据类型”,本质是变量里不放真实数据,只放一个内存地址——就像你通讯录里存的不是朋友本人,而是他的手机号。这个地址指向堆内存中某个对象的实际位置。String、ArrayList、int[]、自定义类的对象,全属此类。String s = "hello" 这行代码中,s 本身不包含字符,它只是个“指针”,指向堆里那块存着 "hello" 的内存。
为什么改了方法里的数组,原数组也变了?
因为方法传参时,Java对引用类型只复制地址(即“引用的副本”),不是复制整个对象。所以 change(arr) 中的 arr 和外面的 arr 指向同一块堆内存。你在方法里执行 arr[0] = 100,等于直接改了那块内存里的内容。
但注意这个常见误区:
- ✅ arr[0] = 100 → 原数组变
- ❌ arr = new int[]{9,8,7} → 原数组不变(这只是让方法内的 arr 指向新地址,不影响外部变量)
基本类型 vs 引用类型:赋值行为完全不同
赋值时的区别最能暴露本质:
-
int a = 5; int b = a;→b得到的是5的一份独立拷贝;改a不影响b -
int[] x = {1,2}; int[] y = x;→y得到的是和x一样的地址;改x[0]就等于改y[0]
这也就是为什么用 == 比较两个 String 变量时,很可能返回 false——它比的是地址是否相同,不是内容。
立即学习“Java免费学习笔记(深入)”;
容易被忽略的坑:String 看似引用,实则“假装不可变”
String 是引用类型,但它被设计成不可变(immutable)。所以 s = s + "!" 并不是在原字符串上追加,而是新建一个对象,再把 s 指向它。这时候原来的引用就断开了。
这意味着:
- 频繁拼接字符串用
String会反复创建对象,性能差 → 改用StringBuilder -
String s1 = "abc"; String s2 = "abc";可能指向常量池同一个地址(s1 == s2为true),但new String("abc")一定新建对象(==为false)
真正理解引用,关键不在记住定义,而在每次写 = 或传参时,心里默念一句:“我是在复制地址,还是在复制值?”









