如何在java中克隆多维数组?

编辑2:下面是一个基于DuffyMo响应的代码片段,演示了如何使用System.arraycopy克服多维数组克隆的局限性。

import java.util.Arrays; public class Randar { public static int[][] arrayMaster = {{6,1}, {10,1}, {1,1}}; private static int[][] arrayChanges = new int[arrayMaster.length][2]; public Randar () { } public static void main(String[] args) { arrayChanges[0][0] = 0; resetArrays(arrayChanges, arrayMaster); arrayChanges[0][0] = 0; System.out.format("arrayMaster: %s, arrayChanges: %s", Arrays.deepToString(arrayMaster), Arrays.deepToString(arrayChanges)); } public static void resetArrays(int[][] arrayChanges, int[][] arrayMaster) { for (int a=0; a< arrayMaster.length; a++) { System.arraycopy(arrayMaster[a], 0, arrayChanges[a], 0, arrayMaster[a].length); } // arrayChanges = arrayMaster.clone(); will NOT work as expected } } 

[原始问题]在Java中(完全)克隆多维数组的简单方法是什么? 这个程序说明了我的问题。

 import java.util.Arrays; public class Randar { public static int[][] arrayMaster = {{6,1}, {10,1}, {1,1}}; static private int[][] arrayChanges = arrayMaster; public static void main(String[] args) { arrayChanges[0][0] = 0; resetArrays(); System.out.format("arrayMaster: %s, arrayChanges: %s",Arrays.deepToString(arrayMaster), Arrays.deepToString(arrayChanges)); } public static void resetArrays() { arrayChanges = arrayMaster.clone(); } } 

运行上面的代码时,arrayMaster和arrayChanges一样,与我的意图相反。 考虑到我可以克隆arrayMaster的每个单维数组成员,我试图解决这个问题:

 for (int iter = 0; iter < arrayMaster.length; iter++) { arrayChanges[iter] = arrayMaster[iter].clone(); } 

但是当我运行由于某种原因而给出NullPointerException的代码时。 写一个循环遍历数组的各个整数值的方法是我唯一的选择吗?

谢谢。

编辑1:这也无法解决问题。

 import java.util.Arrays; public class Randar { public int[][] arrayMaster = {{6,1}, {10,1}, {1,1}}; private int[][] arrayChanges = arrayMaster.clone(); public Randar () { } public static void main(String[] args) { Randar Randar1 = new Randar(); Randar1.arrayChanges[0][0] = 0; resetArrays(Randar1.arrayChanges, Randar1.arrayMaster); Randar1.arrayChanges[0][0] = 0; System.out.format("arrayMaster: %s, arrayChanges: %s", Arrays.deepToString(Randar1.arrayMaster), Arrays.deepToString(Randar1.arrayChanges)); } public static void resetArrays(int[][] arrayChanges, int[][] arrayMaster) { /*for (int a=0; a< arrayMaster.length; a++) { System.arraycopy(arrayMaster[a].clone(), 0, arrayChanges[a], 0, arrayMaster[a].length); } */ arrayChanges = arrayMaster.clone(); } } 

运行上面的代码时,arrayMaster和arrayChanges一样,与我的意图相反。

这条线

 static private int[][] arrayChanges = arrayMaster; 

是罪魁祸首。 此arrayChangesarrayMaster指向同一个对象,因此当您从任一对象访问对象时,可以看到对任一对象的更改。

编辑:每当克隆多维数组的一个维度时会发生什么

正如Eric Lippert解释的那样 ,数组在概念上是一个变量列表。 如果你只是指定另一个变量来指向同一个数组,那么la static private int[][] arrayChanges = arrayMaster; ,你根本没有改变变量集。 除了arrayChanges之外,您还没有创建任何新变量,因此您没有从操作系统/ JVM获得更多内存,因此您对arrayMaster任何更改都将应用于arrayChanges ,反之亦然。

现在让我们来看一个二维数组。 在Java中,二维数组是一个变量列表,恰好具有这些变量中的每一个引用一维数组的属性。 因此,无论何时克隆二维数组,都会创建一个新的变量列表,每个变量都指向旧变量所指向的相同位置。因此,您已经获得了一些可以安全地编写arrayChanges[0] = new int[10]而不影响arrayMaster ,但是一旦开始引用arrayChanges[i][j]你仍然引用arrayMaster引用的相同的二级数组。 你真正想要的是深度复制二维数组的int是

 public static int[][] deepCopyIntMatrix(int[][] input) { if (input == null) return null; int[][] result = new int[input.length][]; for (int r = 0; r < input.length; r++) { result[r] = input[r].clone(); } return result; } 

对于那些可能会在未来看到这个答案的人:是的,最好用T替换int并使方法通用,但为此目的,更具体的深度复制方法更容易解释。

clone做一个“浅”的副本。 也就是说,最外面的数组是重复的,但存储在其中的值不变。 因此,如果您有A1 = {B1,B2,B3}并将其克隆到A2中,则A2的初始内容将为{B1,B2,B3}。 如果将A1更改为{C1,B2,B3},则A2将保持不变,但如果更改B1的内容(不替换它),则A2将“看到”该更改。

要完成您想要的任务,您必须遍历外部数组并clone该外部数组的元素(它们是内部数组)。

Pidgin Java:

 int[][] A2 = A1.clone(); for (int i = 0; i < A2.length; i++) { A2[i] = A2[i].clone(); }