int[][] array = new int[][] {...}
int[][] clone = array.clone();
我天真地期待这个工作。但它没有 - 它只克隆了第一个维度,如果我想要一个真正的克隆,我必须手动克隆另一个维度。注意:内容已正确复制。但是,当我更改clone[0][1]
时,它会反映在array[0][1]
虽然已知.clone()
执行浅层克隆,int[][]
看起来像一个对象(如果我们至少不了解其内部实现)
为什么选择这种行为?是不是int[][]
引用了一个数组对象,而不仅仅是数组的第一个维度?在什么情况下只克服第一个维度所需的行为?
答案 0 :(得分:8)
为什么选择这种行为?
一致性,很有可能。
正如您所说,int[][]
引用了一个数组对象。碰巧每个数组元素的内容都是另一个数组,但这只是一个细节。 Java以相同方式克隆所有数组,并且由于元素可以是任何类型,因此无法保证执行深层复制。
因此,clone()
数组执行浅拷贝,因此只克隆第一个维度。
(一般来说,对于克隆是否暗示深拷贝或浅拷贝的问题,似乎没有单一的“最佳”或“明显”答案。开发人员想要的将取决于每个字段的使用方式应用程序,所以一个通用的方法自然会有限制。)
答案 1 :(得分:3)
这种行为得到了证明,因为没有真正的多维数组。
Java通过生成数组来实现多个维度。这意味着:
int[][] is actually Array<Array<int>>
因此克隆只会复制第一个维度。
如果您尝试使用3维数组,则需要克隆三次。
答案 2 :(得分:1)
clone
方法是一个所谓的浅层副本(参见another stackoverflow answer on the clone
method),这意味着所有元素都是通过引用复制的。
要获得您想要的东西(也称为深度克隆),您可以使用Arrays.copy
递归复制每个单独的数组,这样您找到的每个(子)数组都将获得深度克隆,或者检查this stackoverflow answer on deep cloning
快乐的黑客行为: - )
答案 3 :(得分:1)
我实际上无法复制您提到的行为。我可以看到一些答案提到浅拷贝是问题的根本原因。纠正我,如果我错了,浅拷贝只是意味着克隆时不是复制对象,我们将获得参考的副本。可以在In Java, what is a shallow copy?
找到一个很好的解释在这种情况下,浅拷贝只会确保原始数组中的更改反映在克隆数组中,但不会阻止任何内容被复制。
int[][] array = new int[][] {{1,2,3},{4,5,6}, {7,8,9}};
int[][] clone = array.clone();
//Try this to see magic of shallow copy
//array[2][1]=11;
for(int i=0;i<array.length;i++)
for(int j=0;j<array[i].length;j++)
System.out.println("array["+i+"]["+j+"]"+array[i][j]);
for(int i=0;i<clone.length;i++)
for(int j=0;j<clone[i].length;j++)
System.out.println("clone["+i+"]["+j+"]"+clone[i][j]);
对我来说克隆是完美的,即两个数组都有相同的内容。我能想到克服数组的问题不能显示某些信息的唯一原因是我们在克隆之后实际修改了原始数组(然后浅层拷贝进入播放)。
BTW我使用的是Java 1.6,我希望这不是问题。
编辑:如果我们只需要理解为什么它们是浅拷贝而不是多维数组的深拷贝。让我们来看看2个事实
现在结合1和2,我们知道Java中的多维数组只是一个对象,它引用了其他数组对象。
类似于ArrayObj-&gt; {ArrayObj,ArrayObj,ArrayObj};
因为我们在对象(组合)中有对象,所以我们应该根据Java克隆规则获得浅拷贝。