Понимание примера эффективного глубокого копирования Java

В 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?

Разве глубокая копия в основном не означает: опускаться до тех пор, пока не будут достигнуты примитивные типы, а затем скопировать их в клон?

Спасибо за любой намек на это!


person stefan.at.wpf    schedule 29.03.2013    source источник


Ответы (2)


Это «глубокая копия», в которой изменения в связанном списке исходного объекта (через next) не будут видны в копии или наоборот. Сравните это с «поверхностной копией», которая была бы сделана, если бы новый объект просто скопировал исходную ссылку next.

Однако это неглубокая копия с точки зрения ключа и значения - если это изменяемые типы и они мутированы, то да, мутация будет видна как в исходной, так и в «клонированной» версии.

Таким образом, в конечном счете, это более глубокая копия, чем наивный подход "копировать все ссылки", но это не полностью глубокая копия.

person Jon Skeet    schedule 29.03.2013
comment
очень понятный ответ, спасибо! не знал, что есть eep copy и полностью глубокая копия. Также спасибо CapnSmack за его ответ :-) - person stefan.at.wpf; 30.03.2013

Когда вы создаете глубокую копию, недостаточно иметь «те же» записи в новой HashTable. Вы должны создать новые экземпляры для каждой из этих записей. В противном случае каждая таблица будет содержать ссылку на один и тот же объект записи. Затем, когда кто-то изменяет значение в первой таблице, оно также будет изменено во второй таблице (новая копия).

person CapnSmack    schedule 29.03.2013