метод clone против конструктора копирования в java. который является правильным решением. где использовать каждый случай?
Clone() vs Copy constructor - который рекомендуется в 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()
имеет множество проблем с дизайном, как указано в других ответах), а конструктор-копир потребует ручной работы:
-
BeanUtils.cloneBean(original)
создает неглубокий клон, как тот, который созданObject.clone()
. (этот класс из commons-beanutils) -
SerializationUtils.clone(original)
создает глубокий клон. (т.е. клонируется весь класс свойств, а не только первый уровень) (из commons-lang), но все классы должны реализоватьSerializable
-
Библиотека глубокого клонирования Java предлагает глубокое клонирование без необходимости реализации
Serializable
Ответ 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
правильно реализовано.
Ответ 5
См. также: Как правильно переопределить метод клонирования?. Клонирование нарушено на Java, так трудно понять это правильно, и даже когда это происходит, на самом деле это не очень много, поэтому на самом деле это не стоит проблем.
Ответ 6
Великая печаль: ни Клонируемый/клон, ни конструктор - отличные решения: Я НЕ ХОЧУ ЗНАТЬ ИСПОЛНИТЕЛЬНЫЙ КЛАСС!!! (например, у меня есть карта, которую я хочу скопировать, используя ту же скрытую реализацию MumbleMap), я просто хочу сделать копию, если это поддерживается. Но, увы, Cloneable не имеет на него метода clone, поэтому нет ничего, к которому вы можете безопасно вводить тип, на который нужно вызвать clone().
Независимо от лучшей библиотеки "экземпляр-копия", Oracle должна сделать ее стандартным компонентом следующей версии Java (если она уже не скрыта).
Конечно, если большая часть библиотеки (например, - Коллекции) была неизменной, эта задача "копирования" просто исчезла бы. Но тогда мы начали бы разрабатывать Java-программы с такими вещами, как "инварианты класса", а не с шаблоном "bean" (сделать сломанный объект и мутировать до хорошего [достаточно]).