Java的方法传值

Posted on 2020-12-02,3 min read
  • 首先先声明结论,Java的方法传递的是值。对于Java的对象来说传递的是对象引用的副本。
  • 具体还得从局部变量表说起
    • 局部变量表定义:局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。局部变量表的容量以变量槽(Variable Slot)为最小单位。
    • 对于局部变量表的每一个变量槽。都能存放一个boolean、byte、char、short、int、float、reference或returnAddress类型的数据。而其中reference就是代表的一个对象的引用(数组也是引用类型)
    • 如果执行的是实例方法,那么局部变量表中0位索引的变量槽默认是用于传递方法所属对象实例的应用(this),其余参数按照参数表顺序排列。再根据方法体内部定义的变量顺序和作用域分配其余变量槽
  • 也就是说,参数传入到局部变量表里的实际上是一个引用。那为什么说Java是按值传递的呢?因为这个引用实际上是一个传入对象的引用的一个副本,而非是对象真正的引用。关于这方面可以参考微软对引用的定义。地址
  • 对于对象进行修改操作,是可以直接反应到对象上的(如:传入的是一个map对象,调用put方法)。而对于对象的赋值操作,则不会反应到对象上(如:传入了一个对象,并在方法内把它指向null传入的方法 = null)。
    首先,定义一个对象,作为测试使用
class MyObject {
    public int number;
}

然后定义一个swap方法,用于交换两个对象。

public static void swap(MyObject a, MyObject b) {
    MyObject c = a;
    a = b;
    b = c;
}

定义main方法进行测试。

public 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);
}

结果显而易见,10和20

[0.030s][info][gc] Using G1
10 20

Process finished with exit code 0

接着,我们在swap后对a进行一个a.number++的操作。

public static void swap(MyObject a, MyObject b) {
    MyObject c = a;
    a = b;
    b = c;
    a.number++;
}
[0.030s][info][gc] Using G1
10 21

Process finished with exit code 0

此时,打印出来的结果是10 和 21。
因为在交换后,局部变量a的指向地址已经是调用者b的指向地址了。所以修改的值对于调用者来说是修改的b的值。


下一篇: Java HashMap源码分析→

loading...