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?


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

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.


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
}

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));                                                               
    }                                                                                                                                                    
}                                                                                                                                                        
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.