JAVA 参数传递是值传递还是引用传递

-「JAVA 参数传递是值传递还是引用传递?」
-「JAVA 参数的传递是值传递。」

所谓 值传递 - Pass By Value 是指在调用方法时将参数复制一份传递到方法中,这样在方法中如果对参数进行修改,将不会影响到实际参数。
所谓 引用传递 - Pass By Reference 是指在调用方法时将实际参数直接传递到函数中,那么在方法中对参数所进行的修改,将影响到实际参数。

先看一个简单的例子:

在方法中传递基本的数据类型

public class MyTest {
    public void use(int arg) {
        arg = arg + 1;
        System.out.println(arg);
    }

    public static void main(String[] args) {
        MyTest test = new MyTest();
        int a = 1;
        System.out.println(a);      // 1
        test.use(a);                // 2
        System.out.println(a);      // 1
    }
}

从结果可以看出来,在方法内部修改基本数据类型如 int 的值不会对原始的参数的值产生影响,这是因为把 arg=1 拷贝到方法的内部,在方法内修改的只是原始值的拷贝,自然不会对原始值产生影响。

但是,如果由上述得出 java 是值传递的,一定会有人跳出来反驳,例如下面的例子:

public class MyTest {
    public void use(Map map) {
        map.put("age", 18);
        System.out.println(map);
    }

    public static void main(String[] args) {
        MyTest test = new MyTest();
        Map map = new HashMap<>();
        map.put("name", "yuhao");
        System.out.println(map);        //{name=yuhao}
        test.use(map);                  //{name=yuhao, age=18}
        System.out.println(map);        //{name=yuhao, age=18}
    }
}

可以看出传入方法的是引用类型的 HashMap ,在方法内部修改的 map 的内容,在方法外面是有体现的。那是否可以据此得出对于引用类型的参数,java 是传引用的呢?

其实是把引用拷贝了一份在方法内,只是在方法内修改是这个引用指向的内容,而并没有修改引用本身,因此,在方法外面也反应出了这种变化。

复制了就是传值, 没复制就是传引用。

传递的内容是引用类型 != 引用传递。

如果,java 是引用传递的话,那么在方法的内部,对参数的指向进行的修改,那在方法的外部也应该是变化的。

java 规范中表明,java 引用类型的值,指的就是指针,并不是对象本身。通过 java 中的修改引用类型的值,是指对这个变量进行重新赋值。

另外一个简单的证明 java 不是引用拷贝的例子

public class MyTest {
    private void init(MyTest objVar) {
        System.out.println(objVar);  // null
        objVar = new MyTest();
        System.out.println(objVar);  // MyTest@1b6d3586
    }

    public static void main(String[] args) {
        MyTest arg = null;
        MyTest test = new MyTest();
        test.init(arg);
        system.out.println(arg);     // null

        //After calling init method, arg still points to null
        //this is because arg is passed as value and not as reference.
    }
}

C++ 是支持引用传递的

#include <iostream>

int func(int& a, int& b)
{
    // a 和 b 均是实参 a 的别名
    a = 3; // 把实参 a 修改为 3
    b = 4; // 把实参 a 修改为 4
    return a + b; // 4 + 4 = 8
}

int main()
{
    int a = 1, b = 2, c = func(a, a);
    std::cout << a << b << c; // 428
}