Search code examples
javaclone

Do the clone() method must clone all the references in all the levels in an object?


When we override the clone() method in Java we need to make sure that the cloned object is not affecting the original one, therefore the references to instances inside of the original object must be cloned too, instead of being simply copied.

In the "Effective Java" book I've found this example:

class HashTable implements Cloneable{

    private Entry[] buckets;

    // ...

    private static class Entry{
        Object key;
        Object value;
        Entry next;

        Entry(Object key, Object value, Entry next){
            this.key = key;
            this.value = value;
            this.next = next;
        }

        Entry deepCopy(){
            return new Entry(key, value,
                    next == null ?
                        null :
                        next.deepCopy());
        }
    }

    @Override
    public Object clone() throws CloneNotSupportedException{
        HashTable result = (HashTable) super.clone();

        result.buckets = new Entry[buckets.length];

        for(int i=0; i<buckets.length; i++){
            if(buckets!=null){
                result.buckets[i] = buckets[i].deepCopy();
            }
        }

        return result;
    }

    // ...

}

Now, inside of the clone() method we have the fix for the default super.clone() method, which copies the references. So it creates a new empty bucket for the clone object:

result.buckets[i] = buckets[i].deepCopy();

then it loops in the bucket and it does a deep copy of all the elements in the buckets array:

for(int i=0; i<buckets.length; i++){
    if(buckets!=null){
        result.buckets[i] = buckets[i].deepCopy();
    }
}

And actually, the deepCopy() method is copying the elements in the array, one by one, following the chain of entries.

Since we are not cloning the keys and the values for the "cloned" entries of the cloned object, they will be pointing to the same objects. That means that it is possible to change one of the value references in the cloned version and affect the original object.

So, we are only cloning the array containing the entries, but not the entries themselves.

Is it legit? To what extent do we have to clone the references in an object?


Solution

  • Since we are not cloning the keys and the values for the "cloned" entries of the cloned object, they will be pointing to the same objects. That means that it is possible to change one of the value references in the cloned version and affect the original object.

    That is legit, since the semantics of Java collections are that they store references; therefore, a new collection with the same references is a valid copy of the original collection.