java只有值传递,基本类型传数值副本,引用类型传引用值(对象地址的副本)的副本;形参修改对象状态会影响实参,但重新赋值形参不影响实参引用指向。

Java 中并不存在“传递对象地址”的说法,方法调用时传递的始终是**引用的副本**(即引用值),而不是对象本身,也不是 C/C++ 意义上的内存地址。理解这一点是掌握 Java 参数传递机制的关键。
Java 只有值传递,没有引用传递
Java 所有参数传递都是值传递:基本类型传的是数值的副本,引用类型传的是引用变量中存储的值(即对象在堆中的地址值)的副本。这个值本身是一个类似“指针地址”的数字(JVM 内部表示,开发者不可见、不可操作),但 Java 不允许你直接访问或修改它。
- 形参得到的是实参引用的一个拷贝,两者指向同一个堆对象
- 你可以通过这个引用来读写对象状态(如修改成员变量)
- 但如果你在方法内让形参指向新对象(如 obj = new Person()),不会影响实参引用原本指向的对象
典型例子:能改内容,不能改引用指向
看这段代码:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
public static void modify(Person p) {
p.name = "Alice"; // ✅ 修改成功:通过引用副本操作了原对象
p = new Person("Bob"); // ❌ 实参不受影响:只是改变了形参 p 的指向
}
调用前:main 中的 person 引用指向堆中某 Person 实例
调用后:person.name 变为 "Alice",但 person 仍指向原对象,不是新创建的 "Bob"
为什么不能说“传地址”?
虽然底层实现确实用地址定位对象,但 Java 抽象层屏蔽了地址操作:
- 你无法获取、打印、计算或强制转换这个“地址值”(没有 &、*、uintptr_t 等)
- 引用变量不是指针类型,不支持算术运算或地址比较(== 比较的是引用值是否相等,即是否指向同一对象)
- JVM 可能在 GC 时移动对象,自动更新所有引用值——说明你持有的根本不是稳定地址
如何验证传的是引用值的副本?
一个简单实验:
Person a = new Person("Tom");
System.out.println(System.identityHashCode(a)); // 输出哈希码(近似地址标识)
modify(a);
System.out.println(System.identityHashCode(a)); // 值不变 → 引用没变
即使在 modify 方法里重新赋值 p = new Person(...),a 的 identityHashCode 依然不变,证明实参引用本身未被修改。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










