📌 核心结论
Java 只有值传递(Pass by Value),没有引用传递(Pass by Reference)。
无论是基本数据类型还是对象类型,传递的都是变量值的副本。区别在于:
-
基本类型传递的是数据值的副本(如
int a = 10
,传递的是10
的副本)。 -
对象类型传递的是对象引用的副本(如
Object obj = new Object()
,传递的是引用地址的副本,而非对象本身)。
📝 代码验证:基本类型 vs 对象类型
1. 基本数据类型(值传递副本)
public static void main(String[] args) {
int a = 10;
modify(a);
System.out.println(a); // 输出 10(原值未变)
}
static void modify(int num) {
num = 20; // 修改的是副本
}
关键点:
-
num
是a
的副本,修改num
不影响原变量a
。
2. 对象类型(传递引用的副本)
public static void main(String[] args) {
Person p = new Person("Alice");
modifyReference(p);
System.out.println(p.getName()); // 输出 Alice(原引用未变)
modifyObject(p);
System.out.println(p.getName()); // 输出 Bob(对象内容被修改)
}
static void modifyReference(Person person) {
person = new Person("Bob"); // 修改的是引用的副本
}
static void modifyObject(Person person) {
person.setName("Bob"); // 修改对象内部状态
}
关键点:
-
modifyReference
:方法内person
是原引用的副本,指向新对象不影响原引用。 -
modifyObject
:通过副本引用修改对象内容,原对象状态会改变。
❌ 常见误区与面试题
误区1:“Java 对象是引用传递”
反驳:对象传递的是引用值的副本,而非引用本身。方法内无法直接修改原引用指向的对象。
误区2:“String 对象不可变,所以是值传递”
解析:String 的不可变性与传递机制无关。以下代码验证:
public static void main(String[] args) {
String s = "Hello";
modifyString(s);
System.out.println(s); // 输出 Hello
}
static void modifyString(String str) {
str = "World"; // 修改的是引用的副本
}
-
str
是s
的副本,重新赋值不影响原引用。
高频面试题
-
如何解释 Java 是值传递?
答:传递的是变量值的副本,基本类型传数据副本,对象类型传引用地址的副本。 -
以下代码输出什么?为什么?
public static void swap(Person p1, Person p2) { Person temp = p1; p1 = p2; p2 = temp; }
答:无法交换原
p1
和p2
,因为方法内交换的是副本引用。 -
如何让方法内修改影响外部对象引用?
答:需要将对象包装在另一个对象中(如AtomicReference
或自定义容器类)。
💡 总结
-
值传递的本质:传递的是变量值的副本。
-
对象类型的行为:通过副本引用修改对象内容会影响原对象,但修改引用本身(指向新对象)不影响原引用。
-
面试技巧:结合代码和内存模型图解释,避免陷入“引用传递”的表述陷阱。
通过理解这一机制,可以避免因错误理解导致的逻辑 Bug(如误以为方法内修改引用会影响外部变量)。