狂野飙车6鸿蒙版
471.84M · 2025-10-31
原文来自于:zha-ge.cn/java/26
那天在面试中,技术官问了一个看似简单的问题:"Java 方法传参是值传递还是引用传递?"
我自信满满地回答:"基本类型是值传递,对象是引用传递!"
面试官微笑着在白板上写下了这段代码:
public void swap(Integer a, Integer b) {
Integer temp = a;
a = b;
b = temp;
}
// 调用
Integer x = 10, y = 20;
swap(x, y);
System.out.println("x=" + x + ", y=" + y); // 结果是什么?
"你觉得 x 和 y 会交换吗?" 面试官问道。
我愣住了。按照我的理解,Integer 是对象,应该是引用传递,x 和 y 应该会交换才对!
结果当然没变,输出是 x=10, y=20,根本没有交换!
这时我意识到,我对 Java 传参机制的理解有误。面试官接着展示了另一个例子:
public void modifyList(List<String> list) {
list.add("新元素");
list = new ArrayList<>(); // 重新赋值
list.add("这个不会影响原list");
}
List<String> myList = new ArrayList<>();
myList.add("原始元素");
modifyList(myList);
// myList 里有什么?
答案是 ["原始元素", "新元素"]。第二个赋值操作并没有影响到原来的 list!
面试官解释说:Java 中永远只有值传递,没有引用传递!
理解"值"的关键在于:
用快递来比喻:
| 传参类型 | 比喻 | 实际情况 |
|---|---|---|
| 基本类型 | 给你一份文件的复印件 | 修改副本不影响原件 |
| 对象类型 | 给你一张地址纸条的复印件 | 通过地址能找到同一个房子,但换掉纸条不影响原地址 |
看这段代码:
public void testReference(StringBuilder sb) {
sb.append("_modified"); // 能修改对象内容
sb = new StringBuilder("new"); // 重新赋值不影响外部
}
StringBuilder original = new StringBuilder("hello");
testReference(original);
System.out.println(original); // 输出: hello_modified
为什么 append 有效而重新赋值无效?
因为方法接收的是引用地址的副本:
这次面试让我明白:
现在每当有人问起 Java 传参机制,我都会先讲这个 swap 的故事,然后强调:
理解这一点后,很多困惑就迎刃而解了。你是否也曾被这个概念困扰过呢?