Java只有值传递:基本类型传数值副本,引用类型传地址副本;可修改对象属性,但不能改变原变量指向或置null。

Java 中只有值传递,没有引用传递——这是语言规范决定的,不是实现细节或版本差异。和其他支持真正引用传递的语言(如 C++、C#)对比,关键不在“能不能改对象内容”,而在于“能不能让外部变量指向新对象”。
Java 的值传递:传的是“引用地址的副本”
对基本类型,传的是数值本身(比如 5);对对象或数组,传的是堆中对象地址的副本(比如 0x7f8a)。形参和实参是两个独立变量,只是初始时指向同一块内存。
- ✅ 可以通过副本地址修改原对象的属性(
p.name = "Tom"生效) - ❌ 不能让外部变量指向新对象(
p = new Person("Jerry")不影响原变量) - ❌ 不能让外部变量变 null(
p = null只让副本失效,原引用还在)
C++ 的引用传递:传的是变量本身的别名
用 & 声明的参数不是副本,而是原变量的另一个名字,共享同一内存位置。
- ✅ 修改形参等价于直接修改实参(
int& x = a;后x = 100就是a = 100) - ✅ 可以让实参指向新对象(
Person*& p = ptr;后p = new Person()会改变外部指针) - ✅ 可以把实参设为 null(
p = nullptr直接清空原始指针)
C# 的 ref/out 机制:显式启用引用传递
必须在调用方和被调用方都加 ref 关键字,编译器强制你意识到“这不是副本”。
- ✅
void Swap(ref int a, ref int b)真正交换两个变量的值 - ✅
void Reset(ref Person p)中p = null会让外部变量也变 null - ⚠️ 不加
ref时,C# 对对象的默认行为和 Java 一样:传引用的副本
为什么 Java 不提供引用传递?
设计上追求简单与安全:避免方法意外篡改调用方的变量绑定关系,降低副作用风险。所有变量绑定(谁指向谁)都由调用方完全控制,方法只能操作对象状态,不能接管引用本身。
这使得 Java 的行为可预测——无论传什么,你永远知道:方法内重新赋值不会影响外面的变量。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











