通过 Arrays.copyOf() 生成的二维数组副本中的更改反映在原始数组中

如果我在 Java 中创建一个二维 int 数组,然后使用 Arrays.copyOf() 复制它,就像这样 -

If I create a 2D int array in Java, and then make a copy of it using Arrays.copyOf(), like so -

jshell> int[][] c1 = {{1,2}, {3,4}}
c1 ==> int[2][] { int[2] { 1, 2 }, int[2] { 3, 4 } }

jshell> int[][] d1 = Arrays.copyOf(c1, c1.length)
d1 ==> int[2][] { int[2] { 1, 2 }, int[2] { 3, 4 } }

如果我随后更改副本中的一个元素,为什么原始二维数组中的相应单元格会在此过程中发生突变?

If I then change an element in the copy, why does the corresponding cell in the original 2D array get mutated in the process?

jshell> d1[0][0] = 0
$21 ==> 0

jshell> d1
d1 ==> int[2][] { int[2] { 0, 2 }, int[2] { 3, 4 } }

jshell> c1
c1 ==> int[2][] { int[2] { 0, 2 }, int[2] { 3, 4 } } // c1[0][0] was 1 originally

这让我相信,在使用 Arrays.copyOf() 复制 2D 数组期间,仅为最外层数组创建单独的副本,而每个内部数组仍然是对原始二维数组的内部数组?

This leads me to believe that during a copy of 2D arrays using Arrays.copyOf(), a separate copy is created only for the outermost array, while each inner array is still a reference to the inner arrays of the original 2D array?

jshell> d1 = null
d1 ==> null

jshell> c1
c1 ==> int[2][] { int[2] { 0, 2 }, int[2] { 3, 4 } }

如果是这样,为什么会这样?不应该 Arrays.copyOf() 创建不同的副本,至少按照 docs?Oracle 文档中是否记录了这种行为?

If so, why is it this way? Shouldn't Arrays.copyOf() create distinct copies, at least per the docs? Is this behavior documented anywhere in the Oracle docs?

最后,创建 2D 数组的不同副本的正确方法是什么,就像 Arrays.copyOf() 用于 1D 数组一样?

Lastly, what is the correct way to create distinct copies of a 2D array, the same way Arrays.copyOf() works for 1D arrays?

推荐答案

二维数组基本上是一个包含数组的数组,而 Arrays.copyOf 做的是浅拷贝,所以只有外层数组(数组的数组)被复制,而不是数组中的值(在这种情况下,int 的数组,即 int[]).因此,原始和副本都包含相同的 int[] 数组,因此如果通过其中一个进行修改,则结果也可以通过另一个看到.

A 2D array is basically an array that contains arrays, and Arrays.copyOf does a shallow copy, so only the outer array (the array of arrays) is copied, not the values inside the array (in this case, arrays of int, ie int[]). As a result, both the original and the copy contain the same int[] arrays, so if you modify through one, the result is also visible through the other.

这在 javadoc 中明确提到:

This is explicitly mentioned in the javadoc:

对于在原始数组和原始数组中都有效的所有索引复制,两个数组将包含相同的值.

For all indices that are valid in both the original array and the copy, the two arrays will contain identical values.

您确实需要在了解签名的情况下阅读:<T>T[] copyOf(T[], int).复制的数组是 T[](T 的数组,其中 Tint[]),而不是T[][]!

You do need to read that with the knowledge of the signature: <T> T[] copyOf(T[], int). The array copied is T[] (an array of T, where T is int[]), not T[][]!

对于二维数组的深拷贝,您必须自己对数组进行深拷贝,例如,请参阅 如何在 Java 中进行二维数组的深拷贝?

For a deep copy of a 2D array, you will have to deep copy the array yourself, for example see How do I do a deep copy of a 2d array in Java?

相关文章