我的变量范围有问题。
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
。
为什么我在方法中更改了数组中的值,但原始数组发生了变化?
答案 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)
说明:
您将数组引用的值传递给test()
方法。由于java是Pass By Value,它传递引用的值,而不是数组的值(即副本)。
如果您有C背景,可能更容易将引用视为指针。所以引用的值本质上是它的内存地址(我在这里捏造java规则,但这样做可能最简单)
因此,在您的示例中,将指向数组的引用值传递给test()
方法,然后使用该引用值查找数组在内存中的位置,以便它可以访问数组中的数据。
由于在test()
方法中,您没有更改数组的引用(它指向的位置,即test = new int[10];
),因此您的test()
方法会对数组中的原始数据起作用(因为它仍指向原始数组的位置),导致元素0
设置为5
的值。