Clone() vs Copy constructor - который рекомендуется в java

метод clone против конструктора копирования в java. который является правильным решением. где использовать каждый случай?

Ответ 1

Клон сломан, поэтому не используйте его.

МЕТОД КЛОНА класса Object является несколько магическим методом, который делает какой чистый метод Java никогда не мог do: он производит идентичную копию его объекта. Он присутствует в Первоначальный суперкласс класса, поскольку Бета-релиз дней Java компилятор *; и это, как и все древние магии, требует соответствующего заклинание для предотвращения заклинания неожиданно ожесточается

Предпочитает метод, который копирует объект

Foo copyFoo (Foo foo){
  Foo f = new Foo();
  //for all properties in FOo
  f.set(foo.get());
  return f;
}

Подробнее http://adtmag.com/articles/2000/01/18/effective-javaeffective-cloning.aspx

Ответ 2

Имейте в виду, что clone() не работает из коробки. Вам нужно будет реализовать Cloneable и переопределить метод clone() в public.

Есть несколько альтернатив, которые предпочтительнее (поскольку метод clone() имеет множество проблем с дизайном, как указано в других ответах), а конструктор-копир потребует ручной работы:

Ответ 3

clone() был разработан с несколькими ошибками (см. этот вопрос), поэтому лучше избегать этого.

Из Effective Java 2nd Edition, пункт 11: разумно переопределить клон

Учитывая все проблемы, связанные с Cloneable, можно с уверенностью сказать, что другие интерфейсы не должны расширять его, а классы, предназначенные для наследования (пункт 17), не должны реализовывать его. Из-за многих недостатков некоторые экспертные программисты просто не рекомендуют переопределять метод клонирования и никогда не вызывать его, кроме, возможно, для копирования массивов. Если вы создаете класс для наследования, имейте в виду, что если вы решите не предоставлять хорошо защищенный метод клонирования, для подклассов невозможно реализовать Cloneable.

В этой книге также описываются многие преимущества, которые создатели копий имеют над Cloneable/clone.

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

Все стандартные коллекции имеют конструкторы копирования. Используй их.

List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);

Ответ 4

Имейте в виду, что конструктор копирования ограничивает тип класса экземпляром конструктора копирования. Рассмотрим пример:

// Need to clone person, which is type Person
Person clone = new Person(person);

Это не работает, если person может быть подклассом person (или если person является интерфейсом). В этом весь смысл клона - это то, что он может динамически клонировать правильный тип во время выполнения (предполагая, что клон правильно реализован).

Person clone = (Person)person.clone();

или

Person clone = (Person)SomeCloneUtil.clone(person); // See Bozho answer

Теперь person может быть любым типом person, предполагая, что clone правильно реализовано.

Ответ 6

Великая печаль: ни Клонируемый/клон, ни конструктор - отличные решения: Я НЕ ХОЧУ ЗНАТЬ ИСПОЛНИТЕЛЬНЫЙ КЛАСС!!! (например, у меня есть карта, которую я хочу скопировать, используя ту же скрытую реализацию MumbleMap), я просто хочу сделать копию, если это поддерживается. Но, увы, Cloneable не имеет на него метода clone, поэтому нет ничего, к которому вы можете безопасно вводить тип, на который нужно вызвать clone().

Независимо от лучшей библиотеки "экземпляр-копия", Oracle должна сделать ее стандартным компонентом следующей версии Java (если она уже не скрыта).

Конечно, если большая часть библиотеки (например, - Коллекции) была неизменной, эта задача "копирования" просто исчезла бы. Но тогда мы начали бы разрабатывать Java-программы с такими вещами, как "инварианты класса", а не с шаблоном "bean" (сделать сломанный объект и мутировать до хорошего [достаточно]).