在Java里方法参数如何传递_Java值传递机制说明

Java中所有方法参数都是值传递,基本类型传值副本,对象类型传引用副本;修改对象属性会影响原对象,但重新赋值形参引用则不会;String等不可变类因创建新对象而看似被修改。

Java中所有方法参数都是值传递,没有引用传递。所谓“值传递”,是指方法接收的是实参的副本,而不是实参本身;即使传入的是对象,传递的也只是对象引用的副本,而非引用本身。

基本类型参数:传递真实值的拷贝

对于 int、double、boolean 等基本类型,方法接收到的是该变量值的一个完全独立副本。修改形参不会影响原始变量。

例如:

int a = 10;
change(a);
System.out.println(a); // 输出仍是 10

void change(int x) { x = 20; }

这里 x 是 a 的副本,x 的修改与 a 无关。

对象类型参数:传递引用的副本

当传入一个对象(如 String、ArrayList、自定义类实例)时,实际上传递的是该对象引用(即内存地址)的一个副本。这个副本和原引用指向同一个堆内存中的对象。

因此,在方法内通过该引用修改对象的属性(比如 list.add()、obj.name = "new"),会影响原对象;但若在方法内让形参引用指向新对象(如 obj = new Person()),则不会改变原始引用所指的对象。

例如:

Person p = new Person("Alice");
modify(p);
System.out.println(p.name); // 输出 "Bob"

void modify(Person person) {
  person.name = "Bob";  // ✅ 修改对象内容,生效
  person = new Person("Charlie"); // ❌ 只改变副本引用,不影响 p
}

String 和包装类是特例:不可变性掩盖了值传递本质

String、Integer、Double 等是不可变类(immutable)。它们看似“被修改”,其实是创建了新对象并让引用指向它。由于传入的是引用副本,方法内重新赋值对原引用无影响。

例如:

String s = "hello";
changeStr(s);
System.out.println(s); // 输出 "hello",不是 "world"

void changeStr(String str) {
  str = "world"; // 创建新字符串,str 指向新对象,原 s 不变
}

想真正实现“引用传递效果”?靠返回值或包装容器

Java 无法直接修改传入的引用本身,但可通过以下方式间接达

成目的:

  • 方法返回新对象,由调用方重新赋值: s = changeStr(s);
  • 传入可变容器(如 AtomicInteger、StringBuilder、List、自定义包装类)来承载数据
  • 将多个相关值封装进一个对象,传对象引用并在内部修改其字段

这些做法不改变 Java 的值传递本质,而是利用对象可变性或显式赋值来达到预期效果。