acautomaton
acautomaton
Published on 2025-03-04 / 7 Visits
0
0

Java 中为什么只有值传递?

值传递 pass by value:在调用函数时,将实际参数复制一份传递到函数中。

引用传递 pass by reference: 在调用函数时,将实际参数的地址直接传递到函数中。

先说结论

Java 是将实际参数的地址拷贝传递到函数中,所以属于值传递。

基本类型及其包装类

执行以下代码:

public class Main {
    public static void main(String[] args) {
        Integer a = 0;
        printAddress(a);
        change(a);
        printAddress(a);
    }

    public static void change(Integer a) {
        a = 1;
        printAddress(a);
    }

    public static void printAddress(Object o) {
        System.out.println("value: " + o +", address: " + System.identityHashCode(o));
    }
}

运行:

value: 0, address: 189568618
value: 1, address: 500977346
value: 0, address: 189568618

标准的值传递。

引用类型(对象,数组,接口等)

执行以下代码:

public class Main {
    public static void main(String[] args) {
        MyObject myObject = new MyObject(0);
        MyObject.printAddress(myObject);
        MyObject.change(myObject);
        MyObject.printAddress(myObject);
    }
}

class MyObject {
    public Integer a;

    public MyObject(Integer a) {
        this.a = a;
    }

    public static void change(MyObject myObject) {
        myObject.a = 1;
        printAddress(myObject);
    }

    public static void printAddress(MyObject myObject) {
        System.out.println("value: " + myObject.a + ", address: " + System.identityHashCode(myObject));
    }
}

运行:

value: 0, address: 793589513
value: 1, address: 793589513
value: 1, address: 793589513

这看起来不是引用传递吗?其实不然。我们将赋值变为 new 试试:

public class Main {
    public static void main(String[] args) {
        MyObject myObject = new MyObject(0);
        MyObject.printAddress(myObject);
        MyObject.change(myObject);
        MyObject.printAddress(myObject);
    }
}

class MyObject {
    public Integer a;

    public MyObject(Integer a) {
        this.a = a;
    }

    public static void change(MyObject myObject) {
        myObject = new MyObject(1);
        printAddress(myObject);
    }

    public static void printAddress(MyObject myObject) {
        System.out.println("value: " + myObject.a + ", address: " + System.identityHashCode(myObject));
    }
}

运行:

value: 0, address: 793589513
value: 1, address: 186370029
value: 0, address: 793589513

可以看出,传递的是对象的地址的拷贝,否则,函数外的对象的地址也会改变。那为什么在前一个例子中, a 的值发生了变化?因为改变的是对象的地址指向的堆中的 a ,对象的地址不会发生变化。


Comment