这个问题在这里已有答案:
为什么数组的输出给出b的修改值;
public static void main(String[] args)
{
int i=0;
int a[] = {1,2,3,4};
int b[] = {5,6,7,8};
a=b;
b[2] = 9;
while(i<4)
{
System.out.println(a[i]);
i++;
}
}
在Java中,字节数组是一种特殊类型的对象。在这种情况下,您使用的是类型为I[
的整数数组。在Java中,始终引用对象实例而不是按值保存。您可以很好地看到如果将它们打印出来会发生什么:
int[] a = { 1, 2, 3, 4 };
int[] b = { 5, 6, 7, 8 };
System.out.printf("Before: a=%s b=%s%n", a, b);
a = b;
System.out.printf("After: a=%s b=%s%n", a, b);
b[2] = 9;
System.out.println(Arrays.toString(a));
将打印出来:
Before: a=[I@15db9742 b=[I@6d06d69c
After: a=[I@6d06d69c b=[I@6d06d69c
[5, 6, 9, 8]
正如你所看到的那样,它将参考文献打印为I[
类型,然后是@
,然后是参考文献。首先,引用指向两个不同的对象实例,但在a = b
之后,a
和b
都引用了首次分配给b
的对象实例。这意味着a
和b
的任何改变都将在同一个对象上。当然,如果你打印出a
或b
的值也没关系。
如果你想确保在更改a
时没有改变b
,那么你需要克隆该对象。数组在实现Cloneable
接口时支持克隆:
int[] a = { 1, 2, 3, 4 };
int[] b = { 5, 6, 7, 8 };
System.out.printf("Before: a=%s b=%s%n", a, b);
a = b.clone();
System.out.printf("After: a=%s b=%s%n", a, b);
b[2] = 9;
System.out.println(Arrays.toString(a));
将打印出来:
Before: a=[I@15db9742 b=[I@6d06d69c
After: a=[I@7852e922 b=[I@6d06d69c
[5, 6, 7, 8]
正如您所看到的,a
现在指向一个全新的数组实例,其原始值首先由b
引用。
请注意,打印对象引用适用于数组,因为数组不实现toString
,当预期使用String
时会自动调用Object#toString
。在这种情况下,它使用toString
打印参考,如下所示。
如果实现了System.identityHashCode(variable)
,则无法打印出对象实例的引用。相反,如果引用相等,您可以使用if (a == b)
作为指示。或者您可以简单地使用Is Java "pass-by-reference" or "pass-by-value"?来测试参考相等性。
因为a和b具有相同的参考。并且基本上是相同的数据。
a=b;
当你写a
然后b
和{5,6,7,8};
指向相同的阵列,即a
。
然后,无论您是通过b
还是for(int i = 0 ; i<a.length() , i++) // assume the size of two array are equal
{
b[i] = a[i] ;
}
更新它都会对同一个数组进行更改。
A = B 这是浅拷贝,因为a和b具有相同的引用,数组“a”的任何更改都将改变数组“b”
如果要复制值(深层复制)
qazxswpoi
在进行数组声明时,只有花括号中的那些声明实际存储在内存中。 (实际上,存储了更多信息,但是对于你的问题的范围,你可以假装它只是花括号中的内容)
您的变量'a'和'b'只是在内存中指向花括号中值的位置的引用。
因此,当你说a = b时,你的数组引用'a'不再指向其存储值的原始位置,而是指向'b'指向的位置和存储值。