HOWTO · Java

在 Java 中数组是以值传递还是以引用传递

本文介绍了 Java 中检查数组是按值传递还是按引用传递。

本页内容

Java 对所有方法参数都采用值传递。当参数是数组时,复制到形参中的值是指向数组对象的引用。因此,调用方和形参可以引用同一个对象,但它们仍是两个独立变量。这解释了为什么修改数组元素对调用方可见,而把另一个数组赋给形参却不会影响调用方。

Java 如何传递参数

引用是一种让代码能够访问对象的值;引用本身不是对象。方法接收的是引用值的副本。方法调用开始时,调用方的数组变量和方法形参都引用同一个数组对象。Java 不会按引用传递数组变量本身,因此方法无法通过给自己的形参赋值来替换调用方的变量。

关键区别在于修改对象和修改变量。给数组元素赋值会修改共享对象;给形参赋值只会改变形参中的引用副本。尽管这两种操作都发生在被调用的方法内,它们产生的效果却不同。

修改数组元素会如何影响调用方

方法写入 values[index] 时,会修改两个引用都能访问到的数组对象中的一个元素。方法返回后,调用方也能看到该元素的变化。这里按值传递的是引用;元素修改之所以可见,是因为引用副本仍指向同一个对象。

方法重新赋值数组形参时会发生什么

把一个新数组赋给形参后,形参会改为引用另一个对象。这不会改变调用方的变量;调用方的变量仍引用原来的数组。重新赋值之前对原对象所做的修改,调用方仍能看到,但调用方不会获得形参中的新引用。若要替换调用方的数组变量,可以返回新数组,并在调用处将返回值赋给该变量;也可以直接修改原数组。

基本类型形参的行为

基本类型参数同样按值传递:形参一开始持有基本类型值的副本。如果方法给这个形参赋了另一个数值,调用方的变量不会改变。这与重新给数组形参赋值类似,而不同于修改数组元素。数组的情况多了一层引用:复制得到的引用值可用于修改共享对象,而赋予新引用只会影响局部形参。

运行下面这个完整示例:

本节中的代码以及显示的标签或输出仍为英文。

public class ArrayArgumentDemo {
    static void changeFirst(int[] values) {
        values[0] = 9;
    }

    static void replaceParameter(int[] values) {
        values = new int[] {7, 8};
    }

    static void changeNumber(int number) {
        number = 9;
    }

    public static void main(String[] args) {
        int[] numbers = {1, 2};
        changeFirst(numbers);
        System.out.println(numbers[0]);
        replaceParameter(numbers);
        System.out.println(numbers[0]);

        int count = 1;
        changeNumber(count);
        System.out.println(count);
    }
}
9
9
1

第一条打印语句显示元素已经改变。第二条显示,即使方法形参被赋予另一个数组,调用方的数组仍保持不变。最后一条显示调用方的基本类型变量也没有改变。

要点总结

Java 始终按值传递参数,包括数组引用。当调用方和方法形参引用同一个数组对象时,对数组元素的修改会对调用方可见。重新给形参赋值只会改变它的局部引用;给基本类型形参赋值也只会改变它的局部副本。把对象修改与形参赋值区分开,就能准确判断这些操作的影响。