clone() 方法是否必须克隆对象中所有级别的所有引用?

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

当我们覆盖 Java 中的 clone() 方法时,我们需要确保克隆的对象不会影响原始对象,因此必须克隆对原始对象内部实例的引用也,而不是简单地复制。

在 "Effective Java" 书中我找到了这个例子:

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;
    }

    // ...

}

现在,在 clone() 方法内部,我们修复了默认的 super.clone() 方法,它会复制引用。 所以它为克隆对象创建了一个新的空桶:

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

然后它在桶中循环并对buckets数组中的所有元素进行深度复制:

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

实际上,deepCopy() 方法是按照条目链一个接一个地复制数组中的元素。

由于我们没有克隆克隆对象的 "cloned" 条目的键和值,因此它们将指向相同的对象。这意味着可以更改克隆版本中的 value 引用之一并影响原始对象。

所以,我们只是克隆包含条目的数组,而不是条目本身。

合法吗? 我们必须在多大程度上克隆对象中的引用?

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.

这是合法的,因为 Java 集合的语义是它们存储引用;因此,具有相同引用的新集合是原始集合的有效副本。