¿Llamar a clone () en una matriz también clona su contenido?


92

Si invoco el clone()método en una matriz de objetos de tipo A, ¿cómo clonará sus elementos? ¿La copia hará referencia a los mismos objetos? ¿O llamará (element of type A).clone()a cada uno de ellos?


3
Tienes que llamar a clone en cada elemento.
Peter Lawrey

Respuestas:


77

clone()crea una copia superficial. Lo que significa que los elementos no se clonarán. (¿Y si no lo implementaron Cloneable?)

Es posible que desee utilizar Arrays.copyOf(..)para copiar matrices en lugar de clone()(aunque la clonación está bien para matrices, a diferencia de cualquier otra cosa)

Si desea una clonación profunda, marque esta respuesta


Un pequeño ejemplo para ilustrar la poca profundidad de clone()incluso si los elementos son Cloneable:

ArrayList[] array = new ArrayList[] {new ArrayList(), new ArrayList()};
ArrayList[] clone = array.clone();
for (int i = 0; i < clone.length; i ++) {
    System.out.println(System.identityHashCode(array[i]));
    System.out.println(System.identityHashCode(clone[i]));
    System.out.println(System.identityHashCode(array[i].clone()));
    System.out.println("-----");
}

Huellas dactilares:

4384790  
4384790
9634993  
-----  
1641745  
1641745  
11077203  
-----  

2
Y, si fueras a hacer eso, personalmente usaríaSystem.arrayCopy
corsiKa

1
clone()es una buena opción para usar con matrices ... casi exclusivamente. Bloch menciona que lo usaría solo para matrices y nada más. System.arrayCopyestá bien. Arrays.copyOf(..)es otra alternativa más fácil de utilizar.
Bozho

Lo Arrays.copyOfretiro, usaría :-) Tiene una firma de método que simplifica las variables (sí, te limita, pero es perfecto para la mayoría de los casos) y en mi JDK al menos, se implementa usando de System.arrayCopytodos modos. ¡Gracias por ese consejo!
corsiKa

@Bozho, de tu eg. array [i] y clone [i] se referirían al mismo objeto, por lo que los dos primeros sistemas son iguales. Pero matriz [i] .clone también se referiría a la matriz [i] en sí misma, entonces, ¿por qué matriz [i] .clone () devuelve un valor de código hash diferente?
abhihello123

@weakstudent, array[i].clone()NO hace referencia a array[i]. Eso es lo que está demostrando esa parte del ejemplo.
Dathan

19

Si invoco el método clone () en una matriz de objetos de tipo A, ¿cómo clonará sus elementos?

Los elementos de la matriz no se clonarán.

¿La copia hará referencia a los mismos objetos?

Si.

¿O llamará (elemento de tipo A) .clone () para cada uno de ellos?

No, no llamará clone()a ninguno de los elementos.


6

La matriz 1D de primitivas copia elementos cuando se clona. Esto nos tienta a clonar una matriz 2D (matriz de matrices).

Recuerde que la clonación de matriz 2D no funciona debido a la implementación de copia superficial de clone().

public static void main(String[] args) {
    int row1[] = {0,1,2,3};
    int row2[] =  row1.clone();
    row2[0] = 10;
    System.out.println(row1[0] == row2[0]); // prints false

    int table1[][]={{0,1,2,3},{11,12,13,14}};
    int table2[][] = table1.clone();
    table2[0][0] = 100;
    System.out.println(table1[0][0] == table2[0][0]); //prints true
}

1
¿Me está diciendo que puedo una clonematriz 1D de primitivas y obtener una copia en profundidad? ¡Eso es tan increíble! Vaya bien Arrays.copyOfRange(), System.arraycopy()!
Janez Kuhar

1
¡Yessssss! La matriz 1D de primitivas se copia cuando se clona la matriz
Thamme Gowda

1
Tenga en cuenta que Thamme Gowda N dice "primitivos". Los clones de matrices de objetos serán simplemente un clon de referencias.
Kristiaan

debido a que los primitivos no tienen estado, son inherentemente inmutables. No puede hacer una copia superficial de las primitivas, ya que no hay referencia
Xerus

5

El clon es una copia superficial de la matriz.

Este código de prueba imprime:

[1, 2] / [1, 2]
[100, 200] / [100, 2]

porque MutableIntegerse comparte en ambas matrices como objects[0]y objects2[0], pero puede cambiar la referencia objects[1]independientemente de objects2[1].

import java.util.Arrays;                                                                                                                                 

public class CloneTest {                                                                                                                                 
    static class MutableInteger {                                                                                                                        
        int value;                                                                                                                                       
        MutableInteger(int value) {                                                                                                                      
            this.value = value;                                                                                                                          
        }                                                                                                                                                
        @Override                                                                                                                                        
        public String toString() {                                                                                                                       
            return Integer.toString(value);                                                                                                              
        }                                                                                                                                                
    }                                                                                                                                                    
    public static void main(String[] args) {                                                                                                             
        MutableInteger[] objects = new MutableInteger[] {
                new MutableInteger(1), new MutableInteger(2) };                                                
        MutableInteger[] objects2 = objects.clone();                                                                                                     
        System.out.println(Arrays.toString(objects) + " / " + 
                            Arrays.toString(objects2));                                                                
        objects[0].value = 100;                                                                                                                          
        objects[1] = new MutableInteger(200);                                                                                                            
        System.out.println(Arrays.toString(objects) + " / " + 
                            Arrays.toString(objects2));                                                               
    }                                                                                                                                                    
}                                                                                                                                                        
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.