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

时间:2014-02-08 23:22:40

标签: java variables scope

我的变量范围有问题。

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 3,但结果为5 2 3。 为什么我在方法中更改了数组中的值,但原始数组发生了变化?

2 个答案:

答案 0 :(得分:8)

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

在C中,这将表示为:

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

将该变量传递给方法时,您将传递的参考值(已复制)传递给方法中的本地(堆栈)变量。不复制数组的内容,只复制参考值。再次,就像将指针传递给C中的函数一样。

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

您评论说您通过int[] temp=test对数组进行了“复制”...再次,这只会生成指向内存中单个数组的引用值(指针)的副本。您现在有三个变量都对同一个数组保持相同的引用(一个在main()中,两个在您的方法中)。

如果要复制数组的内容,Java提供static method in the Arrays class

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

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

答案 1 :(得分:0)

说明:

  • Reference =一个变量,指向数组所在的内存中的位置。
  • 参考值=实际的内存地址位置

您将数组引用的值传递给test()方法。由于java是Pass By Value,它传递引用的值,而不是数组的值(即副本)。

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

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

由于在test()方法中,您没有更改数组的引用(它指向的位置,即test = new int[10];),因此您的test()方法会对数组中的原始数据起作用(因为它仍指向原始数组的位置),导致元素0设置为5的值。