Java 方法传参,到底是值还是引用?

原文来自于:zha-ge.cn/java/26

Java 方法传参,到底是值还是引用?

面试中的困惑

那天在面试中,技术官问了一个看似简单的问题:"Java 方法传参是值传递还是引用传递?"

我自信满满地回答:"基本类型是值传递,对象是引用传递!"

面试官微笑着在白板上写下了这段代码:

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 传参机制的理解有误。面试官接着展示了另一个例子:

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 只有值传递

面试官解释说:Java 中永远只有值传递,没有引用传递!

理解"值"的关键在于:

  • 基本类型:传递的是数据本身的副本
  • 对象类型:传递的是引用地址的副本

用快递来比喻:

传参类型 比喻 实际情况
基本类型 给你一份文件的复印件 修改副本不影响原件
对象类型 给你一张地址纸条的复印件 通过地址能找到同一个房子,但换掉纸条不影响原地址

核心理解:引用的副本 ≠ 引用传递

看这段代码:

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 有效而重新赋值无效?

因为方法接收的是引用地址的副本

  • 可以通过这个副本地址修改同一个对象
  • 但改变副本本身(重新赋值),不会影响原来的引用

经验总结

这次面试让我明白:

  1. 概念要精准:Java 没有 C++ 的引用传递,统一都是值传递
  2. 区分对象和引用:修改对象内容与改变引用指向效果不同
  3. 包装类的注意事项:Integer、String 等不可变对象,重新赋值不会影响原值

现在每当有人问起 Java 传参机制,我都会先讲这个 swap 的故事,然后强调:

Java 只有值传递,对象传递的是引用地址的值!

理解这一点后,很多困惑就迎刃而解了。你是否也曾被这个概念困扰过呢?

相关推荐
SimonKing17 小时前
OpenCode AI辅助编程,不一样的编程思路,不写一行代码
java·后端·程序员
FastBean17 小时前
Jackson View Extension Spring Boot Starter
java·后端
Seven9719 小时前
剑指offer-79、最⻓不含重复字符的⼦字符串
java
皮皮林5511 天前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java
冰_河1 天前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化
桦说编程1 天前
从 ForkJoinPool 的 Compensate 看并发框架的线程补偿思想
java·后端·源码阅读
躺平大鹅1 天前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者1 天前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺1 天前
搞懂@Autowired 与@Resuorce
java·spring boot·后端