System.arrayCopy()复制对象或对象的引用?

我有一个最终的类NameAndValue 。 我使用System.arrayCopy()复制了一个NameAndValue对象数组,当我在复制的数组中更改了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,对吧? 为什么会改变?

System.arrayCopy()复制对象或对象的引用?

参考,这是一个浅层副本。 令人惊讶的是, 文档并没有明确地说 ,只是隐含地说,因为它们讨论复制数组元素,而不是递归地复制它们引用的东西。

这与你有这个完全相同:

 NameAndValue nv1 = new NameAndValue("A", "1"); NameAndValue nv2 = nv1; nv2.value = "4"; System.out.println(nv1.value); // 4 

每个数组元素都类似于上面的nv2nv2变量。 正如nv2nv2引用(指向)相同的底层对象一样,数组条目也是如此,包括何时将这些条目从一个数组复制到另一个数组。

它会被更改,因为两个数组仍然引用相同的底层对象。 您可以将新对象分配给数组中的某个位置,但它不会反映在另一个数组中,但如果您对两个数组所指向的对象进行修改,则两者都会以不同方式看到它。

在这个意义上,它通过“按值引用”,而不是通过引用严格传递 – 但您看到的效果是因为引用保持不变。

除非另有明确说明,否则这样的副本几乎总是Java中的浅拷贝。 这也不例外。

据我所知, arraycopy是一个浅拷贝。 这意味着新数组将引用旧数组中元素的地址。 因此,如果您调整其中一个值,它将反映两者

System.arraycopy是一个浅表副本。 这是为什么:

它使用JNI来使用类似memcpy()的东西,它只是复制内存中的指针。 这是一个非常快速的操作。

  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]