Для чего вы использовали Object.clone ()? - PullRequest
14 голосов
/ 07 ноября 2008

Недавно мой коллега спросил меня, как глубоко клонировать Карту, и я понял, что, вероятно, никогда не использовал метод clone (), что меня беспокоит.

Какие наиболее распространенные сценарии, которые вы нашли, когда вам нужно клонировать объект?

Ответы [ 5 ]

15 голосов
/ 07 ноября 2008

Я предполагаю, что вы имеете в виду Object.clone() в Java. Если да, имейте в виду, что Object.clone() имеет некоторые серьезные проблемы, и его использование не рекомендуется в большинстве случаев. Пожалуйста, см. Пункт 11 из «Эффективная Ява» Джошуа Блоха для полного ответа. Я полагаю, что вы можете безопасно использовать Object.clone() для массивов примитивного типа, но помимо этого вы должны быть осторожны в правильном использовании и переопределении клона. Возможно, вам лучше определить конструктор копирования или метод статической фабрики, который явно клонирует объект в соответствии с вашей семантикой.

5 голосов
/ 07 ноября 2008

Чаще всего, когда мне приходится возвращать изменяемый объект вызывающей стороне, я боюсь, что вызывающая сторона может его испортить, часто недружественным способом. Списки и Дата - это те, которые я делаю для большинства. Если вызывающая сторона, вероятно, захочет перебрать список, и у меня есть потоки, возможно, обновляющие его, безопаснее вернуть клон или его копию.

На самом деле, это вызывает то, что мне придется открыть еще один вопрос: копировать конструкторы или клонировать? Когда я делал C ++, мы ВСЕГДА делали конструктор копирования и реализовывали клон с ним, но FindBugs не нравится, если вы реализуете свой клон с помощью конструктора копирования.

3 голосов
/ 07 ноября 2008

Когда мне нужно сделать дубликат чего-либо, чтобы изменить дубликат, не влияя на оригинал, и, конечно, в этом сценарии будет достаточно глубокого клонирования (только). Я должен был сделать это в системе, где я должен клонировать экземпляр класса домена, применить изменения пользователя, а затем выполнить сравнение этих двух параметров, чтобы пользователь проверил их изменения.

2 голосов
/ 07 ноября 2008

Метод Object.clone () не указывает, является ли копия подкласса глубокой или неглубокой копией, он полностью зависит от конкретного класса. Сам метод Object.clone () выполняет поверхностное копирование (копирует внутреннее состояние класса Object), но подклассы должны переопределить его, вызвать super.clone () и при необходимости скопировать свое внутреннее состояние (мелкое или глубокое).

В нем указаны некоторые соглашения, которые вы можете или не должны соблюдать. Для того, чтобы (a.getClass () == a.clone (). GetClass ()) возвратить значение true, следует вызывать super.clone () вместо простого 'new Subclass ()', поскольку предположительно, что super.clone () будет корректно создать экземпляр класса этого объекта (даже в подклассах) и скопировать все внутреннее состояние, включая частные поля, которые не могут быть скопированы подклассами с помощью конструктора копирования, из-за правил видимости. Или вам придется выставить конструктор, который не должен быть выставлен, для лучшей инкапсуляции.

Пример:

//simple clone
class A implements Cloneable {
  private int value;
  public A clone() {
    try {
      A copy = (A) super.clone();
      copy.value = this.value;
      return copy;
    } catch (CloneNotSupportedException ex) {}
  }
}

//clone with deep and shallow copying
class B extends A {
  Calendar date;
  Date date;
  public B clone() {
    B copy = (B) super.clone();
    copy.date = (Calendar) this.date.clone(); // clones the object
    copy.date = this.date; // copies the reference
    return copy;
  }
}

Глубокое копирование обычно используется, когда зависимые объекты являются изменяемыми (например, Календарь), и копия должна быть полностью независимой от оригинала.

Когда зависимые объекты являются неизменяемыми (например, Date), совместное использование одного и того же экземпляра обычно не является проблемой, и мелкой копии может быть достаточно.

При использовании Object.clone () вы должны следовать некоторым правилам, но они достаточно просты, чтобы их можно было понять. Вероятно, самая сложная часть - это правильное определение того, как глубоко вы должны копировать в свой граф объектов. Это логическая проблема, а не языковая проблема.

0 голосов
/ 13 декабря 2008

Я использовал Object.clone () в приложении веб-потока Spring, чтобы проверить, что изменилось, когда пользователь редактирует / вводит данные в форму для целей аудита.

В начале потока я вызываю метод clone, который был реализован на объекте поддержки формы, используемом в весеннем веб-потоке, и сохраняю экземпляр клона в сеансе пользователя. После того как пользователь завершил редактирование данных в html-форме и нажал кнопку «Сохранить», я сравниваю новые значения, связанные с объектом поддержки, с клонированным значением, чтобы определить, какие данные изменил пользователь.

Это сработало хорошо и было действительно легко реализовать, у меня действительно не было проблем с клонированием в Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...