更改方法中的数组更改外部的数组

2022-09-01 19:23:27

我对变量的范围有问题。

public static void main(String[] args){
    int[] test={1,2,3};
    test(test);
    System.out.println(test[0]+" "+test[1]+" "+test[2]);
}

static void test(int[] test){
    test[0]=5;
}

我期望输出为 ,但结果是 。为什么我在方法中更改了数组中的值,但原始数组更改了?1 2 35 2 3


答案 1

Java 中的数组是一个对象。当您通过 创建数组时,它会在堆上创建,并返回一个引用值(类似于 C 中的指针)并将其分配给变量。new

在 C 中,这将表示为:

int *array = malloc(10 * sizeof(int));

将该变量传递给方法时,会将分配(复制)的引用值传递给方法中的本地(堆栈)变量。不会复制数组的内容,只会复制引用值。同样,就像在C中传递指向函数的指针一样。

因此,当您通过该引用修改方法中的数组时,您正在修改堆上存在的单个数组对象。

您评论说,您通过以下方式制作了数组的“副本” ...同样,这只会创建指向内存中单个数组的引用值(指针)的副本。现在,您有三个变量都持有对同一数组的相同引用(一个在 , 两个在您的方法中)。int[] temp=testmain()

如果要复制数组的内容,Java Arrays 类中提供了一个静态方法:

int[] newArray = Arrays.copyOf(test, test.length); 

这将在堆上分配一个新的数组对象(由第二个参数指定的大小),将现有数组的内容复制到该数组,然后将对该新数组的引用返回给您。


答案 2

定义:

  • 引用 = 指向内存中数组所在的位置的变量。
  • 引用的值 = 实际内存地址位置本身

已将数组的引用值传递到方法中。由于java是传递值,因此它传递引用的值,而不是数组的值(即副本)。test()

如果您有 C 背景,则将引用视为指针可能更容易。因此,引用的值本质上是它的内存地址(我在这里捏造java规则,但以这种方式思考它可能是最简单的)

因此,在您的示例中,您将指向数组的引用值传递到您的方法中,然后该方法使用该引用值查找数组在内存中的位置,以便它可以访问数组中的数据。test()

由于在方法中,您不会更改数组的引用(它指向的位置,即 ),因此您的方法将作用于数组中的原始数据(因为它仍然指向原始数组的位置),从而导致元素设置为值 。test()test = new int[10];test()05