L'appel de clone () sur un tableau clone-t-il également son contenu?

92

Si j'appelle la clone()méthode sur un tableau d'objets de type A, comment clonera-t-elle ses éléments? La copie fera-t-elle référence aux mêmes objets? Ou cela fera-t-il appel (element of type A).clone()à chacun d'eux?

Szymon
la source
3
Vous devez appeler clone sur chaque élément.
Peter Lawrey

Réponses:

77

clone()crée une copie superficielle. Ce qui signifie que les éléments ne seront pas clonés. (Et s'ils ne l'ont pas mis en œuvre Cloneable?)

Vous voudrez peut-être utiliser Arrays.copyOf(..)pour copier des tableaux au lieu de clone()(bien que le clonage soit bien pour les tableaux, contrairement à quoi que ce soit d'autre)

Si vous voulez un clonage profond, cochez cette réponse


Un petit exemple pour illustrer la superficialité de clone()même si les éléments sont 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("-----");
}

Impressions:

4384790  
4384790
9634993  
-----  
1641745  
1641745  
11077203  
-----  
Bozho
la source
2
Et, si vous deviez faire cela, personnellement, j'utiliseraisSystem.arrayCopy
corsiKa
1
clone()est une bonne option à utiliser avec des tableaux .. presque exclusivement. Bloch mentionne qu'il ne l'utiliserait que pour les tableaux et rien d'autre. System.arrayCopyc'est bien. Arrays.copyOf(..)est une autre alternative plus simple à utiliser.
Bozho
Je le reprends - j'utiliserais Arrays.copyOf:-) Il a une signature de méthode qui simplifie les variables (oui ça vous limite, mais c'est parfait pour la plupart des cas) et dans mon JDK au moins, il est implémenté en utilisant de System.arrayCopytoute façon. Merci pour cette astuce!
corsiKa
@Bozho, de votre exemple. array [i] et clone [i] feraient référence au même objet, donc les deux premiers sysouts sont identiques. Mais array [i] .clone ferait également référence au tableau [i] lui-même alors pourquoi array [i] .clone () renvoie-t-il une valeur de hashcode différente?
abhihello123
@weakstudent, array[i].clone()ne fait PAS référence à array[i]. C'est ce que démontre cette partie de l'exemple.
Dathan
19

Si j'invoque la méthode clone () sur un tableau d'objets de type A, comment clonera-t-elle ses éléments?

Les éléments du tableau ne seront pas clonés.

La copie fera-t-elle référence aux mêmes objets?

Oui.

Ou appellera-t-il (élément de type A) .clone () pour chacun d'eux?

Non, il ne fera appel clone()à aucun des éléments.

Bludzee
la source
6

Le tableau 1D de primitives copie les éléments lorsqu'il est cloné. Cela nous incite à cloner un tableau 2D (Array of Arrays).

N'oubliez pas que le clonage de tableau 2D ne fonctionne pas en raison de l'implémentation de copie superficielle 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
la source
1
Êtes-vous en train de me dire que je peux clone1D tableau de primitives et obtenir une copie complète? C'est tellement génial! Fare bien Arrays.copyOfRange(), System.arraycopy()!
Janez Kuhar
1
Yessssss! Le tableau 1D de primitives est copié lorsque le tableau est cloné
Thamme Gowda
1
Notez que Thamme Gowda N dit «primitifs». Les clones de tableaux d'objets ne seront qu'un clone de références.
Kristiaan
parce que les primitifs n'ont pas d'état, ils sont intrinsèquement immuables. Vous ne pouvez pas faire une copie superficielle des primitives, car il n'y a pas de référence
Xerus
5

Le clone est une copie superficielle du tableau.

Ce code de test imprime:

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

car le MutableIntegerest partagé dans les deux tableaux en tant que objects[0]et objects2[0], mais vous pouvez modifier la référence objects[1]indépendamment 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
la source