Java方法参数传递:值传递还是引用传递?一文搞懂

在Java学习中,“方法参数传递到底是值传递还是引用传递”是一个常见的困惑点。很多初学者会觉得,既然传递的是对象(引用类型),那就是“引用传递”;但实际上,Java中所有参数传递本质上都是值传递。今天我们用最简单的例子,帮你彻底搞懂这个问题。

一、先明确概念:值传递 vs 引用传递

  • 值传递:方法接收的是参数的“副本”,对参数的修改不会影响原变量。比如你把一张纸条(值)递给别人,别人写了字,不会改变你手里的纸条。
  • 引用传递:方法接收的是参数的“引用地址”(类似“钥匙”),对参数的修改会直接影响原对象。比如你把钥匙(引用)给别人,别人用钥匙打开原锁(对象)并修改内容,原锁的内容会变。

关键区别:值传递修改的是“副本”,引用传递修改的是“原对象”。但Java中不存在严格意义的“引用传递”,只有“值传递”。

二、基本类型参数:值传递的直接体现

Java中的基本类型(如intdoubleboolean等)传递时,方法接收的是值的副本。修改参数不会影响原变量。

例子:交换两个int变量的值

public class ValuePassDemo {
    // 定义交换方法
    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    }

    public static void main(String[] args) {
        int x = 10;
        int y = 20;
        swap(x, y); // 调用方法
        System.out.println("x=" + x + ", y=" + y); // 输出:x=10, y=20
    }
}

为什么结果没变?
swap方法中的abxy的“副本”。修改ab(交换)只改变了副本,原变量xy不受影响。

三、引用类型参数:容易混淆的“陷阱”

Java中的引用类型(如对象、数组、接口等)传递时,方法接收的是引用地址的副本。虽然修改的是“地址副本”,但由于副本和原引用指向同一个对象,因此修改对象的属性会影响原对象

误区1:修改对象属性会影响原对象 → 误认为是“引用传递”

class Student {
    String name;
    public Student(String name) {
        this.name = name;
    }
}

public class ReferencePassDemo {
    // 方法:修改Student对象的name属性
    public static void changeName(Student s) {
        s.name = "小明"; // 修改对象属性
    }

    public static void main(String[] args) {
        Student s = new Student("小红");
        changeName(s); // 传递对象引用
        System.out.println(s.name); // 输出:小明(原对象属性被修改)
    }
}

真相
changeName方法接收的是Student对象引用的副本(副本和原引用s指向同一个Student对象)。修改name属性时,实际上是修改了“同一个对象”的内容,因此原对象的属性会变。这是因为引用地址的副本和原引用指向同一对象,而非“引用传递”。

误区2:修改引用本身 → 原对象不受影响

如果在方法中修改引用本身(让引用指向新对象),原对象不会变,这更能证明是“值传递”:

public static void changeReference(Student s) {
    s = new Student("小刚"); // 修改引用指向新对象
}

public static void main(String[] args) {
    Student s = new Student("小红");
    changeReference(s); // 传递原引用
    System.out.println(s.name); // 输出:小红(原对象未被修改)
}

为什么结果没变?
changeReference中的Student s是原引用的“副本”,修改副本指向新对象,原引用main中的s仍指向“小红”。这就是值传递的本质:修改的是“引用地址的副本”,而非原引用本身。

四、总结:Java永远是“值传递”

  • 基本类型:传递“值的副本”,修改副本不影响原变量。
  • 引用类型:传递“引用地址的副本”,修改副本指向的对象属性会影响原对象(因为它们指向同一对象),但修改引用本身(指向新对象)不会影响原对象。

核心结论:Java中所有参数传递都是值传递,不存在“引用传递”。引用类型的特殊性在于“地址副本”和“原对象共享”,而非传递方式本身是“引用传递”。

一句话记住:

  • 值传递:传的是“副本”,改副本不影响原;
  • 引用类型:传的是“地址副本”,共享对象,改属性影响原。
    Java永远是“值传递”!
小夜