java - tridimensionales - Clonación de matrices multidimensionales.
llenar matriz tridimensional java (4)
int[][] array = new int[][] {...}
int[][] clone = array.clone();
Yo ingenuamente esperaba que esto funcionara. Pero no fue así: clonó solo la primera dimensión, y tuve que ir y clonar la otra dimensión manualmente si quería un clon verdadero. Nota: los contenidos fueron correctamente copiados. Pero cuando cambié el clone[0][1]
, se reflejó en la array[0][1]
Y mientras se .clone()
que .clone()
realiza un clon superficial, int[][]
parece un solo objeto (si no conocemos su implementación interna, al menos)
¿Por qué se elige ese comportamiento? ¿ int[][]
referencia a un objeto de matriz, en lugar de solo a la primera dimensión de la matriz? ¿Y en qué escenarios la clonación es solo la primera dimensión del comportamiento deseado?
¿Por qué se elige ese comportamiento?
Consistencia, muy probablemente.
Como usted dice, int[][]
referencia a un objeto de matriz. Da la casualidad de que el contenido de cada elemento de la matriz es otra matriz, pero eso es sólo un detalle. Java clona todas las matrices de manera idéntica, y como los elementos pueden ser de cualquier tipo, no se puede garantizar que realicen una copia profunda.
Por lo tanto, clone()
para matrices realiza una copia superficial, por lo que solo se clona la primera dimensión.
(En general, no parece que haya una sola respuesta "mejor" u "obvia" a la pregunta de si un clon implica copias profundas o superficiales. Lo que el desarrollador desee dependerá de cómo la aplicación usa cada campo, por lo que un enfoque de talla única naturalmente tendrá limitaciones.)
El método de clone
es una llamada copia superficial (consulte otra respuesta de en el método de clone
), lo que significa que todos los elementos se copian por referencia.
Para llegar a lo que quiere (también llamado clonación profunda) puede copiar cada matriz por sí mismo utilizando Arrays.copy
recursiva, por lo que cada (sub) matriz que encuentre obtendrá un clon profundo, o verificará esta respuesta de en profundidad clonación
Feliz piratería :-)
En realidad no puedo replicar el comportamiento que usted ha mencionado. Puedo ver algunas respuestas que mencionan la copia superficial como la causa raíz del problema. Corríjame si estoy equivocado, una copia superficial significa que en lugar de copiar un objeto mientras se clona, obtendremos una copia de la referencia. Una buena explicación se puede encontrar aquí. En Java, ¿qué es una copia superficial?
En este caso, la copia superficial solo se asegurará de que los cambios en la matriz original se reflejen en la matriz clonada, pero no impedirá que se copie nada.
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]);
Para mí, la clonación se realiza a la perfección, es decir, ambas matrices tienen el mismo contenido. La única razón que se me ocurre para resolver el problema es que la matriz clonada no mostrará algo de información porque hemos modificado la matriz original después de la clonación (la copia superficial entra en juego).
BTW usé Java 1.6, espero que no sea un problema.
Edición: si solo necesitamos entender por qué es una copia superficial en lugar de una copia profunda de una matriz multidimensional. Echemos un vistazo a 2 hechos
- Durante la clonación, los Objetos siempre se clonan como copia superficial (copia de referencia del objeto), solo los tipos nativos obtienen una copia real. En Java, ¿qué es una copia superficial?
- Una matriz en java es en realidad un objeto. Es una matriz un objeto en java.
Ahora, combinando 1 y 2, sabemos que la matriz multidimensional en Java es solo un objeto, que tiene referencia de otros objetos de matriz.
Algo como ArrayObj -> {ArrayObj, ArrayObj, ArrayObj};
Y debido a que tenemos Objetos dentro de objetos (composición), se supone que debemos obtener una copia superficial según la regla de clonación de Java.
Este comportamiento se demuestra porque no hay una verdadera matriz multidimensional.
Java logra múltiples dimensiones al hacer matrices de matrices. Lo que significa:
int[][] is actually Array<Array<int>>
Por lo tanto, el clon solo copiaría la primera dimensión.
Si estuviera intentando con una matriz tridimensional, tendría que clonar tres veces.