值传递 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
,对象的地址不会发生变化。