- 首先先声明结论,Java的方法传递的是值。对于Java的对象来说传递的是对象引用的副本。
- 具体还得从局部变量表说起
- 局部变量表定义:局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。局部变量表的容量以变量槽(Variable Slot)为最小单位。
- 对于局部变量表的每一个变量槽。都能存放一个boolean、byte、char、short、int、float、reference或returnAddress类型的数据。而其中reference就是代表的一个对象的引用(数组也是引用类型)。
- 如果执行的是实例方法,那么局部变量表中0位索引的变量槽默认是用于传递方法所属对象实例的应用(this),其余参数按照参数表顺序排列。再根据方法体内部定义的变量顺序和作用域分配其余变量槽
- 也就是说,参数传入到局部变量表里的实际上是一个引用。那为什么说Java是按值传递的呢?因为这个引用实际上是一个传入对象的引用的一个副本,而非是对象真正的引用。关于这方面可以参考微软对引用的定义。地址
- 对于对象进行修改操作,是可以直接反应到对象上的(如:传入的是一个map对象,调用put方法)。而对于对象的赋值操作,则不会反应到对象上(如:传入了一个对象,并在方法内把它指向null
传入的方法 = null
)。
首先,定义一个对象,作为测试使用然后定义一个swap方法,用于交换两个对象。1
2
3class MyObject {
public int number;
}定义main方法进行测试。1
2
3
4
5public static void swap(MyObject a, MyObject b) {
MyObject c = a;
a = b;
b = c;
}结果显而易见,10和201
2
3
4
5
6
7
8public static void main(String[] args){
MyObject a = new MyObject();
MyObject b = new MyObject();
a.number = 10;
b.number = 20;
swap(a, b);
System.out.println(a.number + " " + b.number);
}接着,我们在swap后对a进行一个a.number++的操作。1
2
3
4[0.030s][info][gc] Using G1
10 20
Process finished with exit code 01
2
3
4
5
6public static void swap(MyObject a, MyObject b) {
MyObject c = a;
a = b;
b = c;
a.number++;
}此时,打印出来的结果是10 和 21。1
2
3
4[0.030s][info][gc] Using G1
10 21
Process finished with exit code 0
因为在交换后,局部变量a的指向地址已经是调用者b的指向地址了。所以修改的值对于调用者来说是修改的b的值。