Cómo clonar una matriz multidimensional en java?

Edición 2: A continuación se muestra un fragmento de código basado en la respuesta de DuffyMo que ilustra cómo evitar las limitaciones de la clonación para matrices multidimensionales utilizando 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 } } 

[PREGUNTA ORIGINAL] ¿Qué es una forma simple de clonar (completamente) una matriz multidimensional en Java? Este progtwig ilustra mi problema.

 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(); } } 

Cuando se ejecuta el código anterior, arrayMaster cambia al igual que arrayChanges, al contrario de mis intenciones. Pensando que podía clonar cada miembro de la matriz dimensional única de arrayMaster, traté de resolver el problema con esto:

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

pero cuando ejecuto el código que da una NullPointerException por alguna razón. ¿Mi única opción es escribir un método que recorra los valores enteros individuales de las matrices?

Gracias.

EDIT 1: Esto tampoco soluciona el problema.

 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(); } } 

Cuando se ejecuta el código anterior, arrayMaster cambia al igual que arrayChanges, al contrario de mis intenciones.

La línea

 static private int[][] arrayChanges = arrayMaster; 

es el culpable Esta línea hace que arrayChanges y arrayMaster apunten al mismo objeto, por lo que un cambio en cualquiera de ellos es visible cuando accedes al objeto desde cualquiera de ellos.

EDITAR: ¿Qué sucede cada vez que clona una dimensión de una matriz multidimensional?

Como explica Eric Lippert , una matriz es conceptualmente una lista de variables. Si solo asigna otra variable para apuntar a la misma matriz a la static private int[][] arrayChanges = arrayMaster; , no ha cambiado el conjunto de variables. No ha creado ninguna variable nueva a excepción de los arrayChanges de arrayChanges , por lo que no ha obtenido más memoria del sistema operativo / JVM, por lo que cualquier cambio que realice en arrayMaster se aplicará a los arrayChanges de arrayChanges y viceversa.

Ahora veamos una matriz bidimensional. En Java, una matriz bidimensional es una lista de variables que tiene la propiedad de que cada una de estas variables se refiere a una matriz unidimensional. Por lo tanto, cada vez que clones una matriz bidimensional, creas una nueva lista de variables, cada una apuntando en el mismo lugar en el que apuntaban las variables anteriores. Por lo tanto, has ganado un poco y puedes escribir arrayChanges[0] = new int[10] sin afectar a arrayMaster , pero tan pronto como comience a hacer referencia a arrayChanges[i][j] todavía está haciendo referencia a las mismas matrices de segundo nivel a las que se refiere arrayMaster . Lo que realmente quieres para copiar profundamente una matriz bidimensional de ints es

 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; } 

Para aquellos que puedan ver esta respuesta en el futuro: sí, es mejor reemplazar int con T aquí y hacer el método genérico, pero para este propósito un método de copia profunda más concreto es más fácil de explicar.

clone hace una copia “superficial”. Es decir, la matriz más externa está duplicada, pero los valores almacenados en ella no se modifican. Entonces, si tiene A1 = {B1, B2, B3} y lo clona en A2, el contenido inicial de A2 será {B1, B2, B3}. Si cambia A1 a {C1, B2, B3}, A2 no cambiará, pero si cambia el contenido de B1 (sin reemplazarlo), A2 “verá” ese cambio.

Para lograr lo que desea, debe recorrer la matriz externa y clone los elementos de esa matriz externa (que son las matrices internas).

Pidgin Java:

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