clone(): ArrayList.clone() I thought does a shallow copy

ArrayList<Integer> a=new ArrayList<Integer>();
a.add(5);
ArrayList<Integer> b=(ArrayList<Integer>)a.clone();
a.add(6);
System.out.println(b.toString());

In the above piece of code, i think clone() does a shallow copy. So, b and a should point to the same memory location. However, when i do b.toString(), the answer is only 5. Why is 6 also not displayed if clone() does a shallow copy?


Shallow copy does not mean that they point to the same memory location. That would be just an assignment:List b = a;.

Cloning creates a new instance, holding the same elements. This means you have 2 different lists, but their contents are the same. If you change the state of an object inside the first list, it will change in the second list. (Since you are using an immutable type - Integer - you can't observe this)

However, you should consider not using clone(). It works fine with collections, but generally it's considered broken. Use the copy-constructors - new ArrayList(originalList)


If it was like you thought, then the clone method would be completely useless, because in that case, the following lines would be equivalent:

ArrayList<Integer> b = (ArrayList<Integer>)a.clone();
ArrayList<Integer> b = a;

Cloning is - like in real world scenarios - a process of creating two entities with exactly the same properties (at the time of the cloning operation).

And as Bozho mentioned - avoid the Java clone() concept. Even it's author mentioned, that it is broken.

This question and it's answers are quite valuable and provide a link to Josh Blochs own comments on his piece of work ;-)


This indeed does a shallow copy, here is a comment for clone, from ArrayList source code

Returns a shallow copy of this ArrayList instance. (The elements themselves are not copied.)

To understand this, let's look at a snippet in clone method from ArrayList

v.elementData = Arrays.copyOf(elementData, size);

As we know, when we assign an Object to a variable, JAVA does not make a brand new copy of that Object. Instead, this variable becomes another reference pointing to the original Object.

Thus, elementData are actually storing reference to objects put into this ArrayList. And clone just copy these references, no replicas of Objects are created.

Of course, you can remove or add new reference to a cloned ArrayList.

However, modification of old Objects in one ArrayList will effect the original ArrayList. It's hard to do illustration with your example since Integer is immutable.

To see the side effect, you can define a custom mutable Object

class Person {
        private int a;

        public void setA(int a) {
            this.a = a;
        }
        public int getA() {
            return a;
        }
        @Override
        public String toString() {
            return String.valueOf(a);
        } 
   } 

Then you can use the following code to make test

        Person p1 = new Person();
        Person p2 = new Person();

        ArrayList<Person> tt = new ArrayList<Person>();
        tt.add(p1);
        tt.add(p2);

        ArrayList<Person> yy = (ArrayList<Person>) tt.clone();
        Person vv = yy.get(yy.indexOf(p2));
        vv.setA(12);
        yy.remove(p1);

        System.out.println("tt: " + tt);
        System.out.println("yy: " +yy);

The output should be

tt: [0, 12]
yy: [12]

See the side effect :) ? We only change the element in yy, but it is also reflected in tt.


Shallow Cloning is the default cloning strategy provided by Object.clone() which you are talking about. The clone() method of object class creates a new instance and copy all fields of the Cloneable object to that new instance (either it is primitive or reference). So in the case of reference types only reference bits gets copied to the new instance, therefore, the reference variable of both objects will point to the same object. The example we have seen above is an example of Shallow Cloning.

Deep Cloning As the name suggest deep cloning means cloning everything from one object to another object. To achieve this we need to trick our clone() method to provide our own cloning strategy. We can do it by implementing Cloneable interface and override clone() method in every reference type we have in our object hierarchy and then call super.clone() and these clone() methods in our object’s clone method.

But if you look at the clone() method of ArrayList in the source code, you will see it is externally copying v.elementData = Arrays.copyOf(elementData, size); after calling super.clone(), which means clone() of ArrayList deeply copies it content

public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

To read more about Cloning and its types like deep cloning and shallow cloning please read Java Cloning and Types of Cloning (Shallow and Deep) in Details with Example