Я задаюсь вопросом, существует ли рекомендуемый способ сделать глубокий клон/копию экземпляра в Java.
Я имею 3 решения в виду, но я могу иметь, скучают по некоторым, и я хотел бы иметь Ваше мнение
править: включайте Bohzo предл и совершенствуйте вопрос: это больше о глубоком клонировании, чем мелкое клонирование.
кодируйте клон ручными свойствами после свойств и проверьте, что изменяемые экземпляры клонированы также.
про:
- управление того, что будет выполнено
- быстрое выполнение
недостатки:
- утомительный, чтобы записать и поддержать
- склонная ошибка (скопировать/вставить отказ, недостающее свойство, повторно присвоил изменяемое свойство),
С Вашими собственными отражательными инструментами или с внешним помощником (как джакартская обыкновенная овощная фасоль) легко записать универсальный метод копии, который сделает задание в одной строке.
про:
- легкий записать
- никакое обслуживание
недостатки:
- меньше управления того, что происходит
- ошибка, склонная с изменяемым объектом, если отражательный инструмент не клонирует объекты sub также
- более медленное выполнение
Используйте платформу, которые делают это для Вас, как:
Ленг свободного городского населения SerializationUtils
Java, глубоко клонирующий библиотеку
Dozer
Kryo
про:
- то же как отражение
- больше управления тем, что будет точно быть клонированным.
недостатки:
- каждый изменяемый экземпляр полностью клонирован, даже в конце иерархии
- мог очень не спешить выполняться
javassit, BCEL или cglib могли бы быть использованием для генерации специализированного клона с такой скоростью, как одна рука записала. Кто-то знает lib с помощью одного из этих инструментов с этой целью?
Что я пропустил здесь?
Какой Вы рекомендовали бы?
Спасибо.
commons-lang SerializationUtils - использование сериализации - если все классы находятся под вашим контролем и вы можете принудительно реализовать Serializable
.
Java Deep Cloning Library - используя отражение - в случаях, когда классы или объекты, которые вы хотите клонировать, находятся вне вашего контроля (сторонняя библиотека), и вы не можете заставить их реализовать Serializable
, или в случаях, когда вы не хотите реализовать Serializable
.
commons-beanutils BeanUtils - в большинстве случаев.
Spring BeanUtils - если Вы уже используете весну и, следовательно, имеете эту утилиту на клашпате.
Я сознательно опустил опцию "сделай сам" - API, приведенный выше, обеспечивает хороший контроль над тем, что клонировать, а что нет (например, используя переходный
, или String[] ignoreProperties
), поэтому переосмысление колеса не является предпочтительным.
Вы можете использовать модуль:
module FooProperties
def colour ; "green" ; end
def is_spherical? ; true ; end
end
class Foo
extend FooProperties
include FooProperties
end
немного уродливой, но лучше, чем использование MODIC_MISSING
. Я постараюсь поставить другие варианты в другие ответы ...
Я предложил переопределить Object.CLONE (), вызовите super.clone () сначала и чем вызов ref = ref.clone () на всех ссылках, которые вы хотите иметь глубокий скопированный. Это более или менее Сделайте это сам подход, но нужно немного меньше кодирования.
зависит.
Для скорости используйте DIY. Для пуленепробиваемого, используйте отражение.
Кстати, сериализация не такая же, как отражение, поскольку некоторые объекты могут предоставлять переопределенные методы сериализации (ReadObject / readyObject), и они могут быть багги
Книга Джошуа Блоха имеет целую главу, озаглавленную «Пункт 10: переопределить клону в суде» , в котором он идет, почему переопределение клона по большей части является плохой идеей, потому что Java Spec для этого создает много проблем.
Он предоставляет несколько альтернатив:
используют заводской шаблон вместо конструктора:
общедоступные статические yum newinstance (yum yum);
Используйте конструктор копирования:
публичный ням (ням ням);
Все классы сбора в Java поддерживают конструктор копирования (например, новый ArrayList (L);)
Если есть неожиданный результат, вызовите исключение. Если вы просто хотите, чтобы функция сказала вам «сделал ли я X», то вернуть логическое значение.
-121--2439208- SCOPE _ IDENTITY ()
следует извлечь из первой команды ( SELECT
, RETURN
или OUT
) и передать в следующую команду. Это означает, что SELECT _ IDENTITY ()
должен находиться в конце первой команды . В SQL 2008 имеется дополнительный синтаксис для возврата значений как части INSERT
, что упрощает эту задачу.
Или более эффективно: объедините команды в одну, чтобы избежать обхода.
-121--4780232-Я бы рекомендовал метод DIY, который в сочетании с хорошим методом hashCode () и equals () должен быть легко подтвержден в единичном тесте.