1

在 Effective Java, 2nd Edition, Item 11 中可以找到以下深拷贝示例:

public class HashTable implements Cloneable {
    private Entry[] buckets = ...;

    private static class Entry {
        final Object key;
        Object value;
        Entry next;
        Entry(Object key, Object value, Entry next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

        // Recursively copy the linked list headed by this Entry
        Entry deepCopy() {
            return new Entry(key, value,
                    next == null ? null : next.deepCopy());
        }
    }
    @Override public HashTable clone() {
        try {
            HashTable result = (HashTable) super.clone();
            result.buckets = new Entry[buckets.length];
            for (int i = 0; i < buckets.length; i++)
                if (buckets[i] != null)
                    result.buckets[i] = buckets[i].deepCopy();
            return result;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }

我不明白这是如何进行深层复制的:键和值是对象,因此没有原始类型。所以据我了解,使用

// Recursively copy the linked list headed by this Entry
Entry deepCopy() {
    return new Entry(key, value,
            next == null ? null : next.deepCopy());
}

Entry参考原始的键和值创建一个新的Entry?

深拷贝基本上不是意味着:向下直到达到原始类型,然后将它们复制到克隆?

感谢您对此的任何提示!

4

2 回答 2

5

这是一个“深拷贝”,因为对原始对象的链表(通过next)的更改不会在副本中看到,反之亦然。将其与新对象刚刚复制原始next引​​用时所采用的“浅拷贝”进行比较。

不过,就键和值而言,这是一个浅拷贝——如果它们是可变类型并且发生了变异,那么是的,变异将通过原始版本和“克隆”版本看到。

所以最终,它是比天真的“复制所有引用”方法更深的副本——但它不是一个完全深的副本。

于 2013-03-29T21:41:40.530 回答
1

创建深层副本时,在新的 HashTable 中拥有“相同”的条目是不够的。您必须为每个条目创建新实例。否则,每个表都将保存对同一条目对象的引用。然后,当有人修改第一个表中的值时,它也会在第二个表(新副本)中被修改。

于 2013-03-29T21:43:26.550 回答