Является ли clone () в java мелкой копией? - PullRequest
10 голосов
/ 12 марта 2011

Является ли clone() в Java мелкой копией?

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

Я прочитал это из Википедии .

Я не понимаю, почему это мелкая копия. clone() создаст новый экземпляр со всеми полями. Это просто глубокая копия? смущенный. Нужно какое-то объяснение для меня.

Ответы [ 8 ]

16 голосов
/ 12 марта 2011

По умолчанию Object.clone() действительно мелкая копия. Тем не менее, он предназначен для выброса CloneNotSupportedException, если ваш объект не реализует Cloneable.

И когда вы реализуете Cloneable, вы должны переопределить clone(), чтобы сделать его глубокое копирование, вызвав clone() для всех полей, которые сами клонируются.

5 голосов
/ 12 марта 2011

Кроме того, я удивлен, что никто не упомянул взгляды Джошуа Блоха на Cloneable

Если вы читали статью о клонировании в моей книге, особенно если вы читаете между строк, вы будете знать, что Я думаю, что клон глубоко сломан. Там Есть несколько недостатков дизайна, самый большой из что интерфейс Cloneable не имеет метода клонирования. И это означает, что это просто не работает что-то Cloneable не говорит что-нибудь о том, что вы можете сделать с Это. Вместо этого это говорит кое-что о что он может сделать внутри. Это говорит что если, позвонив super.clone неоднократно это заканчивает тем, что вызывает объект метод клонирования, этот метод вернет полевая копия оригинала.

4 голосов
/ 12 марта 2011

Это мелкая копия, потому что она только копирует ссылку на другие объекты.Скажем, у нас есть эти классы:

class A {
    B variable
    A() {
        variable = new B();
    }
}

class B { }

И теперь мы создаем клон экземпляра A:

A firstA = new A();
A secondA = firstA.clone();

Экземпляр B в firstA и secondA будет одинаковым.У вас не будет копии экземпляра B.Вот почему clone (), как говорят, делает мелкое копирование.

Диаграммы на странице, на которую вы ссылаетесь, должны помочь вам понять все это.

4 голосов
/ 12 марта 2011

clone () создает копию всех полей.Java имеет примитивные типы и ссылки - когда вы клонируете свой объект, вы получаете новый объект с копиями всех примитивных полей (это похоже на глубокую копию), но также у вас есть копия всех полей ссылок.Таким образом, в результате вы получите два объекта с собственными копиями примитивов и копиями ссылок на одни и те же объекты - как исходный, так и скопированный объект будут использовать одни и те же объекты.

3 голосов
/ 12 марта 2011

Некоторые объекты не предоставляют глубокую копию.Например, ArrayList будет клонировать список, но не элементы в списке.Следующее из JavaDoc для ArrayList:

public Object clone()

    Returns a shallow copy of this ArrayList instance. (The elements themselves are not copied.)
2 голосов
/ 12 марта 2011

Реализация Object.clone () по умолчанию является поверхностной копией.Это поведение все еще полезно для типов, которые имеют большое количество примитивных полей или неизменяемых полей.Вы можете посмотреть Как правильно переопределить метод клонирования? Как правильно переопределить его.После вызова super.clone (), а затем приведения полученного объекта клонировать его можно по мере необходимости.

Неявным образом значение клона уменьшается по мере увеличения количества сложных изменяемых полей в вашем типе.

1 голос
/ 12 марта 2011

То, что делает clone, определяется для каждого объекта, который поддерживает клон.Object.clone защищен, поэтому ни один объект не допускает клонирование, если кто-то специально не определил его.

0 голосов
/ 12 марта 2011

Да.

Но сначала вам нужно, чтобы ваш класс реализовал Cloneable и выдал исключение

class A implements Cloneable{
    public int y;
    public B b;

    public A(){
        b = new B();
    }

    public static void main(String[] args) throws CloneNotSupportedException{
        A a = new A();
        A a2 = (A) a.clone();
        System.out.print(a.b==a2.b);
    }
}

Вывод: true

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...