93

If I invoke clone() method on array of Objects of type A, how will it clone its elements? Will the copy be referencing to the same objects? Or will it call (element of type A).clone() for each of them?

Brant Bobby
  • 14,956
  • 14
  • 78
  • 115
Szymon
  • 931
  • 1
  • 6
  • 3

4 Answers4

77

clone() creates a shallow copy. Which means the elements will not be cloned. (What if they didn't implement Cloneable?)

You may want to use Arrays.copyOf(..) for copying arrays instead of clone() (though cloning is fine for arrays, unlike for anything else)

If you want deep cloning, check this answer


A little example to illustrate the shallowness of clone() even if the elements are 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("-----");
}

Prints:

4384790  
4384790
9634993  
-----  
1641745  
1641745  
11077203  
-----  
Community
  • 1
  • 1
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 2
    And, if you were going to do that, personally I'd use `System.arrayCopy` – corsiKa Apr 28 '11 at 16:27
  • 1
    `clone()` is a good option to use with arrays..almost exclusively. Bloch mentions that he would use it only for arrays and nothing else. `System.arrayCopy` is fine. `Arrays.copyOf(..)` is another alternative which is easier to use. – Bozho Apr 28 '11 at 16:30
  • I take it back - I would use `Arrays.copyOf` :-) It has a method signature that simplifies the variables (yes it limits you, but it's perfect for most cases) and in my JDK at least, it's implemented using `System.arrayCopy` anyway. Thanks for that tip! – corsiKa Apr 28 '11 at 16:45
  • @Bozho, from your eg. array[i] and clone[i] would refer to the same object so the first two sysouts are same. But array[i].clone would also refer to array[i] itself so why does array[i].clone() return a different hashcode value? – abhihello123 Nov 02 '13 at 03:28
  • @weakstudent, `array[i].clone()` does NOT refer to `array[i]`. That's what that part of the example is demonstrating. – Dathan Nov 05 '13 at 02:11
19

If I invoke clone() method on array of Objects of type A, how will it clone its elements?

The elements of the array will not be cloned.

Will the copy be referencing to the same objects?

Yes.

Or will it call (element of type A).clone() for each of them?

No, it will not call clone() on any of the elements.

Bludzee
  • 2,733
  • 5
  • 38
  • 46
7

1D array of primitives does copy elements when it is cloned. This tempts us to clone 2D array(Array of Arrays).

Remember that 2D array clone doesn't work due to shallow copy implementation of 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
}
nobody
  • 19,814
  • 17
  • 56
  • 77
Thamme Gowda
  • 11,249
  • 5
  • 50
  • 57
  • 1
    Are you telling me that I can `clone` 1D array of primitives and get a deep copy? That's so awesome! Fare well `Arrays.copyOfRange()`, `System.arraycopy()`! – Janez Kuhar Jul 30 '16 at 19:04
  • 2
    Yessssss! 1D array of primitives are copied when the array is cloned – Thamme Gowda Aug 01 '16 at 14:55
  • 2
    Do note that Thamme Gowda N says "primitives". Clones of arrays of objects will just be a clone of references. – Kristiaan Nov 15 '16 at 09:01
  • because primitives have no state, they are inherently immutable. You cant make a shallow copy of primitives, since there is no reference – xeruf Mar 30 '18 at 22:53
5

The clone is a shallow copy of the array.

This test code prints:

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

because the MutableInteger is shared in both arrays as objects[0] and objects2[0], but you can change the reference objects[1] independently from 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
  • 42,159
  • 20
  • 102
  • 127