Anche la chiamata a clone () su un array ne clona il contenuto?


92

Se invoco il clone()metodo su un array di oggetti di tipo A, come clonerà i suoi elementi? La copia farà riferimento agli stessi oggetti? O richiederà (element of type A).clone()ciascuno di loro?


3
Devi chiamare clone su ogni elemento.
Peter Lawrey

Risposte:


77

clone()crea una copia superficiale. Ciò significa che gli elementi non verranno clonati. (E se non avessero implementato Cloneable?)

Potresti usarlo Arrays.copyOf(..)per copiare gli array invece di clone()(anche se la clonazione va bene per gli array, a differenza di qualsiasi altra cosa)

Se vuoi una clonazione profonda, controlla questa risposta


Un piccolo esempio per illustrare la superficialità clone()anche se gli elementi sono 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("-----");
}

Stampe:

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

2
E, se lo facessi, personalmente System.arrayCopy
userei

1
clone()è una buona opzione da usare con gli array .. quasi esclusivamente. Bloch afferma che lo userebbe solo per gli array e nient'altro. System.arrayCopyè ok. Arrays.copyOf(..)è un'altra alternativa più facile da usare.
Bozho

Lo riprendo - lo Arrays.copyOfuserei :-) Ha una firma del metodo che semplifica le variabili (sì, ti limita, ma è perfetto per la maggior parte dei casi) e almeno nel mio JDK, è implementato usando System.arrayCopycomunque. Grazie per quel suggerimento!
corsiKa

@ Bozho, dal tuo ad es. array [i] e clone [i] farebbero riferimento allo stesso oggetto, quindi i primi due sysout sono gli stessi. Ma array [i] .clone farebbe riferimento anche allo stesso array [i], quindi perché array [i] .clone () restituisce un valore hashcode diverso?
abhihello123

@weakstudent, array[i].clone()NON si riferisce a array[i]. Questo è ciò che sta dimostrando quella parte dell'esempio.
Dathan

19

Se invoco il metodo clone () su un array di oggetti di tipo A, come clonerà i suoi elementi?

Gli elementi dell'array non verranno clonati.

La copia farà riferimento agli stessi oggetti?

Sì.

O chiamerà (elemento di tipo A) .clone () per ciascuno di essi?

No, non richiamerà clone()nessuno degli elementi.


6

L'array 1D di primitive copia gli elementi quando viene clonato. Questo ci induce a clonare un array 2D (Array of Arrays).

Ricorda che il clone di array 2D non funziona a causa dell'implementazione della copia superficiale di 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
Mi stai dicendo che posso un clonearray 1D di primitive e ottenere una copia completa? È fantastico! FARE bene Arrays.copyOfRange(), System.arraycopy()!
Janez Kuhar

1
Yessssss! L'array 1D di primitive viene copiato quando l'array viene clonato
Thamme Gowda

1
Si noti che Thamme Gowda N dice "primitive". I cloni di array di oggetti saranno solo un clone di riferimenti.
Kristiaan

poiché le primitive non hanno uno stato, sono intrinsecamente immutabili. Non puoi fare una copia superficiale delle primitive, poiché non ci sono riferimenti
Xerus

5

Il clone è una copia superficiale dell'array.

Questo codice di prova stampa:

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

perché MutableIntegerè condiviso in entrambi gli array come objects[0]e objects2[0], ma è possibile modificare il riferimento objects[1]indipendentemente da 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));                                                               
    }                                                                                                                                                    
}                                                                                                                                                        
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.