Java所有参数传递都是值传递,基本类型传值副本,引用类型传地址副本;方法内重赋值不影响实参,但修改对象状态会生效,null同理。

Java里所有参数传递都是值传递
Java没有引用传递,连对象也是值传递——只不过这个“值”是对象引用的副本。这意味着:方法内对形参变量的重新赋值(比如 obj = new Object())不会影响实参变量本身;但通过形参修改对象内部状态(比如 list.add("x"))会生效,因为两个引用指向同一个堆内存地址。
基本类型和引用类型的传参表现差异
差异只来自数据存储方式,不是传参机制不同:
- 基本类型(
int、boolean等):栈上存实际值,传的是该值的副本,方法内改它,原变量完全无感 - 引用类型(
String、ArrayList、自定义类等):栈上存的是堆中对象的地址,传的是这个地址的副本;副本和原变量指向同一对象,所以能“看到”对方对对象内容的修改
注意:String 虽是引用类型,但因不可变,任何“修改”操作(如 str.concat())都会生成新对象,原引用不变——这容易让人误以为它像基本类型,其实仍是值传递在起作用。
常见误解场景:swap 方法为什么无效
写一个试图交换两个引用的 swap(Object a, Object b) 方法,运行后原变量没变。这不是 Java 的 bug,而是值传递的必然结果:
立即学习“Java免费学习笔记(深入)”;
- 调用时,
a和b是实参引用值的副本 - 方法内交换的只是这两个副本,不影响调用方栈帧里的原始引用变量
- 没有指针或引用参数语法(如 C++ 的
&或 C# 的ref),无法做到真正交换
如果真需要交换效果,只能靠返回新结构(如 Pair)、或把变量包进容器(如 AtomicReference、数组),让多个引用共同持有可变的“外壳”。
容易被忽略的关键点:null 也是值,且可被覆盖
null 是一个特殊的引用值,和其他引用一样参与值传递:
- 若实参是
null,传入方法的是null这个值的副本 - 方法内给形参赋新对象(如
obj = new Date()),只改变副本,调用方仍为null - 但如果实参是非
null引用,而方法内把它设为null(obj = null),也只是让副本断开连接,原引用不受影响
真正危险的是在方法里对 null 形参做非空操作(如 obj.toString()),会直接抛 NullPointerException——这不是传参机制的问题,而是没校验输入导致的运行时错误。









