Java: рекомендуемое решение для глубокого клонирования/копирования экземпляра

Я задаюсь вопросом, существует ли рекомендуемый способ сделать глубокий клон/копию экземпляра в Java.

Я имею 3 решения в виду, но я могу иметь, скучают по некоторым, и я хотел бы иметь Ваше мнение

править: включайте Bohzo предл и совершенствуйте вопрос: это больше о глубоком клонировании, чем мелкое клонирование.

Сделайте это сами:

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

Отражение использования:

С Вашими собственными отражательными инструментами или с внешним помощником (как джакартская обыкновенная овощная фасоль) легко записать универсальный метод копии, который сделает задание в одной строке.
про:
- легкий записать
- никакое обслуживание
недостатки:
- меньше управления того, что происходит
- ошибка, склонная с изменяемым объектом, если отражательный инструмент не клонирует объекты sub также
- более медленное выполнение

Платформа клона использования:

Используйте платформу, которые делают это для Вас, как:
Ленг свободного городского населения SerializationUtils
Java, глубоко клонирующий библиотеку
Dozer
Kryo

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

Используйте инструментарий байт-кода для записи клона во времени выполнения

javassit, BCEL или cglib могли бы быть использованием для генерации специализированного клона с такой скоростью, как одна рука записала. Кто-то знает lib с помощью одного из этих инструментов с этой целью?

Что я пропустил здесь?
Какой Вы рекомендовали бы?

Спасибо.

173
задан Guillaume 17 May 2017 в 07:07
поделиться

5 ответов

Для глубокого клонирования (клонирования всей объектной иерархии):

  • commons-lang SerializationUtils - использование сериализации - если все классы находятся под вашим контролем и вы можете принудительно реализовать Serializable.

  • Java Deep Cloning Library - используя отражение - в случаях, когда классы или объекты, которые вы хотите клонировать, находятся вне вашего контроля (сторонняя библиотека), и вы не можете заставить их реализовать Serializable, или в случаях, когда вы не хотите реализовать Serializable.

Для мелкого клонирования (клонирование только первого уровня свойств):

  • commons-beanutils BeanUtils - в большинстве случаев.

  • Spring BeanUtils - если Вы уже используете весну и, следовательно, имеете эту утилиту на клашпате.

Я сознательно опустил опцию "сделай сам" - API, приведенный выше, обеспечивает хороший контроль над тем, что клонировать, а что нет (например, используя переходный, или String[] ignoreProperties), поэтому переосмысление колеса не является предпочтительным.

151
ответ дан 23 November 2019 в 20:37
поделиться

Вы можете использовать модуль:

module FooProperties
  def colour ; "green" ; end
  def is_spherical? ; true ; end
end

class Foo
  extend FooProperties
  include FooProperties
end

немного уродливой, но лучше, чем использование MODIC_MISSING . Я постараюсь поставить другие варианты в другие ответы ...

-121--2878056-

Я предложил переопределить Object.CLONE (), вызовите super.clone () сначала и чем вызов ref = ref.clone () на всех ссылках, которые вы хотите иметь глубокий скопированный. Это более или менее Сделайте это сам подход, но нужно немного меньше кодирования.

1
ответ дан 23 November 2019 в 20:37
поделиться

зависит.

Для скорости используйте DIY. Для пуленепробиваемого, используйте отражение.

Кстати, сериализация не такая же, как отражение, поскольку некоторые объекты могут предоставлять переопределенные методы сериализации (ReadObject / readyObject), и они могут быть багги

2
ответ дан 23 November 2019 в 20:37
поделиться

Книга Джошуа Блоха имеет целую главу, озаглавленную «Пункт 10: переопределить клону в суде» , в котором он идет, почему переопределение клона по большей части является плохой идеей, потому что Java Spec для этого создает много проблем.

Он предоставляет несколько альтернатив:

  • используют заводской шаблон вместо конструктора:

      общедоступные статические yum newinstance (yum yum);
     
  • Используйте конструктор копирования:

      публичный ням (ням ням);
     

Все классы сбора в Java поддерживают конструктор копирования (например, новый ArrayList (L);)

35
ответ дан 23 November 2019 в 20:37
поделиться

Если есть неожиданный результат, вызовите исключение. Если вы просто хотите, чтобы функция сказала вам «сделал ли я X», то вернуть логическое значение.

-121--2439208-

SCOPE _ IDENTITY () следует извлечь из первой команды ( SELECT , RETURN или OUT ) и передать в следующую команду. Это означает, что SELECT _ IDENTITY () должен находиться в конце первой команды . В SQL 2008 имеется дополнительный синтаксис для возврата значений как части INSERT , что упрощает эту задачу.

Или более эффективно: объедините команды в одну, чтобы избежать обхода.

-121--4780232-

Я бы рекомендовал метод DIY, который в сочетании с хорошим методом hashCode () и equals () должен быть легко подтвержден в единичном тесте.

1
ответ дан 23 November 2019 в 20:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: