java只有值传递是语言规范的硬性定义:基本类型传数值副本,引用类型传地址副本;形参重赋值不影响实参,但通过副本修改对象内容会影响同一堆内存中的对象。

Java 只有值传递,这句话不是经验总结,而是语言规范的硬性定义。理解它不靠记忆,而要抓住两个关键点:传的是什么、改的是谁。
传的永远是“副本”,不是本体
无论参数是 int 还是 ArrayList,Java 调用方法时,都会把实参当前持有的“那个东西”复制一份,交给形参。这个“那个东西”具体是什么,取决于变量类型:
- 基本类型(如 int、boolean):复制的是数值本身,比如
a = 5,就复制一个5给形参 - 引用类型(如 String、User、int[]):复制的是堆中对象的地址值(即引用),不是对象本身。相当于把“门牌号”抄了一遍,而不是把整栋楼搬过去
改形参 ≠ 改实参,但可能影响实参指向的对象
形参拿到副本后,操作结果分两种情况:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 给形参重新赋值(比如
arr = new int[]{1,2,3}或obj = new User()):只改变形参副本的指向,实参的引用地址不变,外部完全无感 - 通过形参修改对象内容(比如
arr[0] = 999或user.setName("Tom")):因为副本和实参指向同一块堆内存,所以对象内容被改了——但这不是“改了实参”,而是“改了实参也指着的那个对象”
一个试金石例子,直接验证是不是引用传递
看这段代码的输出:
class Node { int val; }static void foo(Node d) { d = new Node(); d.val = 999; }
public static void main(String[] args) {
Node a = new Node(); a.val = 1;
foo(a);
System.out.println(a.val); // 输出 1,不是 999
}
如果 Java 是引用传递,a.val 应该变成 999;但它没变。说明 d = new Node() 只让形参 d 指向了新对象,实参 a 的引用丝毫未动——这正是值传递的铁证。
String 为什么看起来“更像值传递”?
String 是引用类型,但它是不可变的(immutable)。任何“修改”(如 s = s + "!")本质都是创建新字符串并让引用指向它。所以即使在方法里重赋值,实参的引用依然稳稳指着原来的字符串对象,不会受干扰。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










