Java: recommended solution for deep cloning/copying an instance
Java: рекомендуемое решение для глубокого клонирования / копирования экземпляра
Мне интересно, есть ли рекомендуемый способ выполнить глубокое клонирование / копирование экземпляра в java.
У меня есть на примете 3 решения, но я могу пропустить некоторые, и я хотел бы узнать ваше мнение
редактировать: включить предложение Bohzo и уточнить вопрос: речь идет скорее о глубоком клонировании, чем о поверхностном.
Сделай это сам:
вручную кодируйте свойства клонирования после свойств и убедитесь, что изменяемые экземпляры тоже клонированы.
профессиональный: - контроль того, что будет выполняться - быстрое выполнение
минусы: - утомительно писать и поддерживать - подвержен ошибкам (ошибка копирования / вставки, отсутствующее свойство, переназначенное изменяемое свойство)
Используйте отражение:
С помощью ваших собственных инструментов отражения или внешнего помощника (например, jakarta common-beans) легко написать универсальный метод копирования, который выполнит работу в одной строке.
профессиональный: - простота написания - отсутствие обслуживания
минусы: - меньший контроль над тем, что происходит - подвержен ошибкам с изменяемым объектом, если инструмент отражения не клонирует подобъекты тоже - более медленное выполнение
Используйте clone Framework:
Используйте фреймворк, который сделает это за вас, например :
профессиональный: - то же, что и отражение - больше контроля над тем, что именно будет клонировано.
минусы: - каждый изменяемый экземпляр полностью клонируется, даже в конце иерархии - выполнение может быть очень медленным
Используйте инструментарий байт-кода для написания clone во время выполнения
javassit, BCEL или cglib могут использоваться для создания выделенного клонировщика так быстро, как это делается одной рукой. Кто-нибудь знает библиотеку, использующую один из этих инструментов для этой цели?
Что я здесь пропустил? Что бы вы порекомендовали?
Спасибо.
Переведено автоматически
Ответ 1
Для глубокого клонирования (клонирует всю иерархию объектов):
commons-lang SerializationUtils - использование сериализации - если все классы находятся под вашим контролем и вы можете принудительно реализовать Serializable.
Библиотека глубокого клонирования Java - использование отражения - в случаях, когда классы или объекты, которые вы хотите клонировать, находятся вне вашего контроля (библиотека сторонних производителей) и вы не можете заставить их реализовать Serializable, или в случаях, когда вы не хотите реализовывать Serializable.
Для мелкого клонирования (клонирует только свойства первого уровня):
Spring BeanUtils - если вы уже используете spring и, следовательно, имеете эту утилиту в classpath.
Я намеренно опустил опцию "сделай сам" - приведенные выше API обеспечивают хороший контроль над тем, что клонировать, а что нет (например, используя transient, или String[] ignoreProperties), поэтому изобретать велосипед нецелесообразно.
Ответ 2
В книге Джошуа Блоха есть целая глава, озаглавленная "Пункт 10: разумно переопределять клонирование", в которой он объясняет, почему переопределение clone по большей части является плохой идеей, потому что спецификация Java для этого создает много проблем.
Он предлагает несколько альтернатив:
Используйте фабричный шаблон вместо конструктора:
publicstatic Yum newInstance(Yum yum);
Используйте конструктор копирования:
publicYum(Yum yum);
Все классы коллекций в Java поддерживают конструктор копирования (например, new ArrayList(l);)
Kryo работает быстро, на их странице и вы можете найти список компаний, которые используют его в производстве.
Ответ 4
Используйте XStream ToXML / fromXML в памяти. Чрезвычайно быстрый, существует уже давно и успешно развивается. Объекты не обязательно должны быть сериализуемыми, и вам не нужно использовать отражение (хотя XStream использует). XStream может распознавать переменные, указывающие на один и тот же объект, и не создавать случайно две полные копии экземпляра. За эти годы было разработано множество подобных деталей. Я использую его в течение ряда лет, и к нему можно перейти. Он настолько прост в использовании, насколько вы можете себе представить.