我正在上一堂课NameAndValue
。我使用NameAndValue
复制了System.arrayCopy()
个对象的数组,当我在复制的数组中更改了NameAndValue
个对象时,它会反映在原始数组中。
public final class NameAndValue
{
public String name;
public String value;
public NameAndValue()
{
}
public NameAndValue(String name,String value)
{
this.name = name;
this.value = value;
}
}
public class Main
{
public static void main(String[] args)
{
NameAndValue[] nv = new NameAndValue[4];
nv[0] = new NameAndValue("A", "1");
nv[1] = new NameAndValue("B", "2");
nv[2] = new NameAndValue("C", "3");
nv[3] = new NameAndValue("D", "4");
NameAndValue[] nv2 = new NameAndValue[4];
System.arraycopy(nv, 0, nv2, 0, 2);
nv2[2] = new NameAndValue("Y","25");
nv2[3] = new NameAndValue("Z","26");
for (int i = 0; i < 2; i++)
{
NameAndValue[] nv3 = new NameAndValue[4];
System.arraycopy(nv2, 0, nv3, 0, 4);
nv3[2].value = String.valueOf(i);
nv3[3].value = String.valueOf(i+1);
System.out.println(nv2[2].value);
System.out.println(nv2[3].value);
System.out.println("-----------------------");
}
}
}
我的输出为,
0
1
-----------------------
1
2
-----------------------
在所有情况下,我的输出应该是25和26,对吧?为什么会改变?
答案 0 :(得分:19)
System.arrayCopy()将对象或引用复制到对象?
参考,它是浅副本。令人惊讶的是,the docs don't say that explicitly,只是隐含地,因为他们仅谈论复制数组元素,而不是递归地复制他们引用的东西。
这与你有这个完全相同:
NameAndValue nv1 = new NameAndValue("A", "1");
NameAndValue nv2 = nv1;
nv2.value = "4";
System.out.println(nv1.value); // 4
每个数组元素都与上面的nv1
和nv2
变量类似。就像nv1
和nv2
引用(指向)相同的底层对象一样,数组条目也是如此,包括何时将这些条目从一个数组复制到另一个数组。
答案 1 :(得分:2)
它会被更改,因为两个数组仍然引用相同的底层对象。您可以将新对象分配给数组中的某个位置,但不会反映在另一个数组中,但如果您对两个数组所指向的对象进行修改,则两者都会以不同方式看到它。
从这个意义上讲,它是通过“按值引用”,而不是通过引用严格传递 - 但您看到的效果是因为引用保持不变。
除非另有明确说明,否则这样的副本几乎总是Java中的浅拷贝。这也不例外。
答案 2 :(得分:1)
据我所知arraycopy
是一个浅层副本。这意味着新数组将引用旧数组中元素的地址。因此,如果您调整其中一个值,它将反映在两个
答案 3 :(得分:1)
System.arraycopy是一个浅表副本。这就是原因:
它使用JNI来使用类似memcpy()的东西,它只是复制内存中的指针。这是一个非常快速的操作。
答案 4 :(得分:0)
int[] a = {1, 2, 3};
int[] b = new int[3];
System.arraycopy(a, 0, b, 0, 3);
b[1] = 0;
System.out.println(Arrays.toString(b));
System.out.println(Arrays.toString(a));
输出如下: [1,0,3] [1,2,3]
答案 5 :(得分:0)
方法System.arraycopy
不执行数组的深度复制,Arrays.copyOf
方法也不执行。它将引用复制到对象并且不创建新实例。如果您修改其中一个数组中的任何对象,则会影响两个数组:
public static void main(String[] args) {
NameAndValue[] arr1 = new NameAndValue[2];
arr1[0] = new NameAndValue("A", "1");
arr1[1] = new NameAndValue("B", "2");
NameAndValue[] arr2 = new NameAndValue[2];
System.arraycopy(arr1, 0, arr2, 0, 2);
arr2[0].value = "3"; // modify existing object
NameAndValue[] arr3 = new NameAndValue[2];
System.arraycopy(arr1, 0, arr3, 0, 2);
arr3[1] = new NameAndValue("Y", "5"); // create new instance
System.out.println(Arrays.toString(arr1)); // [A:3, B:2]
System.out.println(Arrays.toString(arr2)); // [A:3, B:2]
System.out.println(Arrays.toString(arr3)); // [A:3, Y:5]
}
public static final class NameAndValue {
public String name;
public String value;
public NameAndValue(String name, String value) {
this.name = name;
this.value = value;
}
@Override
public String toString() {
return name + ":" + value;
}
}
另见:
• Why does Array.copyOf() mutate the original array in case of 2D Arrays?
• How do I do a deep copy of a 2d array in Java?