编辑 2:以下是基于 DuffyMo 响应的代码片段,说明了如何使用 System.arraycopy 绕过多维数组的克隆限制.
Edit 2: Below is a code snippet based on DuffyMo's response that illustrates how to get around the limitations of cloning for multidimensional arrays using 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中(完全)克隆多维数组的简单方法是什么?这个程序说明了我的问题.
[ORIGINAL QUESTION] What's a simple way to (fully) clone a multidimensional array in java? This program illustrates my problem.
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 的每个单维数组成员,我试图解决这个问题:
When the above code is run, arrayMaster changes as well as arrayChanges, contrary to my intentions. Thinking that I could clone each single dimensional array member of arrayMaster, I tried to get around the problem with this:
for (int iter = 0; iter < arrayMaster.length; iter++) { arrayChanges[iter] = arrayMaster[iter].clone(); }但是当我运行由于某种原因给出 NullPointerException 的代码时.编写一个循环遍历数组的各个整数值的方法是我唯一的选择吗?
but when I run the code that gives a NullPointerException for some reason. Is writing a method that loops through the individual integer values of the arrays my only option?
谢谢.
编辑 1:这也不能解决问题.
EDIT 1: This doesn't fix the problem either.
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 都发生了变化,这与我的意图相反.
When the above code is run, arrayMaster changes as well as arrayChanges, contrary to my intentions.
线
static private int[][] arrayChanges = arrayMaster;是罪魁祸首.这一行使 arrayChanges 和 arrayMaster 指向同一个对象,因此当您从任一对象访问该对象时,对任一对象的更改都是可见的.
is the culprit. This line makes arrayChanges and arrayMaster point to the same object, so a change to either one is visible when you access the object from either.
克隆多维数组的一维时会发生什么
What happens whenever you clone one dimension of a multidimensional array
正如 埃里克·利珀特解释的那样,一个数组在概念上是一个变量列表.如果你只是分配另一个变量指向同一个数组,比如 static private int[][] arrayChanges = arrayMaster;,你根本没有改变变量集.除了 arrayChanges 之外,您还没有创建任何新变量,因此您没有从操作系统/JVM 中获得更多内存,因此您对 arrayMaster 所做的任何更改都会被应用arrayChanges 反之亦然.
As Eric Lippert explains, an array is conceptually a list of variables. If you just assign another variable to point to the same array a la static private int[][] arrayChanges = arrayMaster;, you haven't changed the set of variables at all. You haven't created any new variables except for arrayChanges, so you haven't gotten more memory from the operating system/JVM, so any change you make to arrayMaster is applied to arrayChanges and vice versa.
现在让我们看一个二维数组.在 Java 中,二维数组是一个变量列表,这些变量恰好具有这些变量中的每一个都引用一个一维数组的特性.因此,无论何时克隆一个二维数组,都会创建一个新的变量列表,每个变量都指向旧变量所指向的同一位置.因此,您可以安全地编写 arrayChanges[0] = new int[10] 不影响 arrayMaster,但是一旦你开始引用 arrayChanges[i][j] 你仍然引用相同的arrayMaster 引用的二级数组.为了深度复制二维整数数组,您真正想要的是
Now let's look at a two-dimensional array. In Java, a two-dimensional array is a list of variables that happens to have the property that each one of these variables refers to a one-dimensional array. So, whenever you clone a two-dimensional array, you create a new list of variables, each pointing in the same place that the old variables pointed in. So, you have gained a little in that you can safely write arrayChanges[0] = new int[10] without affecting arrayMaster, but as soon as you start referencing arrayChanges[i][j] you are still referencing the same second-level arrays that arrayMaster references. What you really want in order to deep-copy a two-dimensional array of ints is
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 并使方法通用,但为此目的更具体的深拷贝方法更容易解释清楚.
To those who may look at this answer in the future: yes, it is better replace int with T here and make the method generic, but for this purpose a more concrete deep copy method is simpler to explain well.