Chamar clone () em uma matriz também clona seu conteúdo?

92

Se eu invocar o clone()método na matriz de objetos do tipo A, como ele clonará seus elementos? A cópia fará referência aos mesmos objetos? Ou vai chamar (element of type A).clone()cada um deles?

Szymon
fonte
3
Você tem que chamar clone em cada elemento.
Peter Lawrey

Respostas:

77

clone()cria uma cópia superficial. O que significa que os elementos não serão clonados. (E se eles não implementaram Cloneable?)

Você pode querer usar Arrays.copyOf(..)para copiar matrizes em vez de clone()(embora a clonagem seja boa para matrizes, ao contrário de qualquer outra coisa)

Se você quiser clonagem profunda, verifique esta resposta


Um pequeno exemplo para ilustrar a superficialidade de clone()até mesmo se os elementos forem 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("-----");
}

Impressões:

4384790  
4384790
9634993  
-----  
1641745  
1641745  
11077203  
-----  
Bozho
fonte
2
E, se você fosse fazer isso, pessoalmente eu usariaSystem.arrayCopy
corsiKa
1
clone()é uma boa opção para usar com arrays ... quase exclusivamente. Bloch menciona que ele o usaria apenas para matrizes e nada mais. System.arrayCopyestá bem. Arrays.copyOf(..)é outra alternativa mais fácil de usar.
Bozho
Retiro - eu usaria Arrays.copyOf:-) Ele tem uma assinatura de método que simplifica as variáveis ​​(sim, limita você, mas é perfeito para a maioria dos casos) e no meu JDK, pelo menos, é implementado usando System.arrayCopyassim mesmo. Obrigado por essa dica!
corsiKa
@Bozho, do seu exemplo, array [i] e clone [i] se referem ao mesmo objeto, então os dois primeiros sysouts são os mesmos. Mas array [i] .clone também se referiria ao próprio array [i], então por que array [i] .clone () retorna um valor hashcode diferente?
abhihello123
@weakstudent, array[i].clone()NÃO se refere a array[i]. Isso é o que essa parte do exemplo está demonstrando.
Dathan
19

Se eu invocar o método clone () na matriz de Objetos do tipo A, como ele clonará seus elementos?

Os elementos da matriz não serão clonados.

A cópia fará referência aos mesmos objetos?

Sim.

Ou irá chamar (elemento do tipo A) .clone () para cada um deles?

Não, não chamará clone()nenhum dos elementos.

Bludzee
fonte
6

A matriz 1D de primitivas copia elementos quando é clonada. Isso nos tenta a clonar array 2D (Array of Arrays).

Lembre-se de que o clone de array 2D não funciona devido à implementação de cópia 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
}
Thamme Gowda
fonte
1
Você está me dizendo que eu posso clone1D array de primitivas e obter uma cópia profunda? Isso é tão incrível! Saem bem Arrays.copyOfRange(), System.arraycopy()!
Janez Kuhar
1
Yessssss! Matriz 1D de primitivas são copiadas quando a matriz é clonada
Thamme Gowda
1
Observe que Thamme Gowda N diz "primitivos". Clones de arrays de objetos serão apenas um clone de referências.
Kristiaan
como os primitivos não têm estado, eles são inerentemente imutáveis. Você não pode fazer uma cópia superficial dos primitivos, pois não há referência
Xerus
5

O clone é uma cópia superficial da matriz.

Este código de teste imprime:

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

porque o MutableIntegeré compartilhado em ambos os arrays como objects[0]e objects2[0], mas você pode alterar a referência objects[1]independentemente 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));                                                               
    }                                                                                                                                                    
}                                                                                                                                                        
Simon Nickerson
fonte