Clone () vs Copy constructor – который рекомендуется в java
clone vs copy в java. который является правильным решением. где использовать каждый случай?
- Соединение RMI отказалось на localhost
- Почему у нас нет статического метода в (нестационарном) внутреннем classе?
- Синхронная версия асинхронного метода
- Как остановить стопку стеков в журналах
- Как вызвать код Java из C #?
- Изменение текущего рабочего каталога в Java?
- Почему String.chars () stream ints в Java 8?
- Является ли отношение IN в Кассандре плохим для запросов?
Клон сломан, поэтому не используйте его.
МЕТОД КЛОНА classа Object – это несколько волшебный метод, который делает то, что никогда не может сделать чистый метод Java: он создает идентичную копию своего объекта. Он присутствует в первозданном суперclassе classа с момента выпуска бета-версии 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
Имейте в виду, что clone()
не работает из коробки. Вам придется реализовать Cloneable
и переопределить метод clone()
созданный public
.
Есть несколько альтернатив, которые предпочтительнее (так как метод clone()
имеет множество проблем с дизайном, как указано в других ответах), а для копирования-конструктора потребуется ручная работа:
-
BeanUtils.cloneBean(original)
создает неглубокий клон, как тот, который был созданObject.clone()
. (этот class – от обыкновенных бханутов ) -
SerializationUtils.clone(original)
создает глубокий клон. (т. е. клонит весь граф свойств, а не только первый уровень) (из commons-lang ), но все classы должны реализовыватьSerializable
-
Библиотека глубокого клонирования Java предлагает глубокое клонирование без необходимости реализации
Serializable
clone () был разработан с несколькими ошибками (см. этот вопрос ), поэтому лучше избегать его.
Из Effective Java 2nd Edition , пункт 11: разумно переопределить клон
Учитывая все проблемы, связанные с Cloneable, можно с уверенностью сказать, что другие интерфейсы не должны расширять его, а classы, предназначенные для наследования (пункт 17), не должны реализовывать его. Из-за многих недостатков некоторые экспертные программисты просто не рекомендуют переопределять метод клонирования и никогда не вызывать его, кроме, возможно, для копирования массивов. Если вы создаете class для наследования, имейте в виду, что если вы решите не предоставлять хорошо защищенный метод клонирования, для подclassов невозможно реализовать Cloneable.
В этой книге также описываются многие преимущества, которые создатели копий имеют над Cloneable / clone.
- Они не полагаются на механизм создания экстралингвистического объекта, подверженного риску
- Они не требуют необоснованного соблюдения тонко документированных конвенций
- Они не противоречат правильному использованию конечных полей
- Они не выбрасывают ненужные проверенные исключения
- Они не требуют отбрасываний.
Все стандартные коллекции имеют конструкторы копирования. Используй их.
List original = // some list List copy = new ArrayList (original);
Имейте в виду, что конструктор копирования ограничивает тип classа экземпляром конструктора копирования. Рассмотрим пример:
// Need to clone person, which is type Person Person clone = new Person(person);
Это не работает, если person
может быть подclassом Person
(или если Person
является интерфейсом). В этом весь смысл клона – это то, что он может динамически клонировать правильный тип во время выполнения (предполагая, что клон правильно реализован).
Person clone = (Person)person.clone();
или
Person clone = (Person)SomeCloneUtil.clone(person); // See Bozho's answer
Теперь person
может быть любым типом Person
предполагающим, что clone
правильно реализован.
См. Также: Как правильно переопределить метод клонирования? , Клонирование нарушено на Java, так сложно понять все правильно, и даже когда это происходит , на самом деле это не очень много , поэтому на самом деле это не стоит того.
Великая печаль: ни Клонируемый / клон, ни конструктор – отличные решения: Я НЕ ХОЧУ ЗНАТЬ ИСПОЛНИТЕЛЬНЫЙ КЛАСС !!! (например, у меня есть карта, которую я хочу скопировать, используя ту же скрытую реализацию MumbleMap), я просто хочу сделать копию, если это поддерживается. Но, увы, Cloneable не имеет клона метод на нем, поэтому нет ничего, к которому можно безопасно вводить тип, на который нужно вызвать clone ().
Какая бы ни была лучшая библиотека «экземпляр-копия», Oracle должна сделать ее стандартным компонентом следующей версии Java (если она уже не скрыта где-то).
Конечно, если бы большая часть библиотеки (например, «Коллекции») была неизменной, эта задача «копировать» просто исчезла бы. Но тогда мы начали бы разрабатывать Java-программы с такими вещами, как «инварианты classа», а не с шаблоном «bean» verdammt (сделать сломанный объект и мутировать до хорошего [достаточно]).