Как я могу создать копию своего типа данных, который я создал в Java? - PullRequest
3 голосов
/ 17 февраля 2010

Если у меня есть класс:

public class MyType  
{  
    private List<Integer> data;  
    private boolean someFlag;

    public MyType(List<Integer> myData, boolean myFlag)
    {
        this.data = myData;
        this.myFlag = someFlag; 
    } 
}

Теперь, если я создаю экземпляр MyType, как мне сделать его полную копию? Я не хочу, чтобы новый объект указывал на старую ссылку, но совершенно новый экземпляр.

Это тот случай, когда я должен реализовать интерфейс Cloneable, или он используется для мелких копий?

Я не могу просто сделать:

MyType instance1 = new MyType(someData, false);  
MyType instance2 = new MyType(instance1.getData(), instance1.getFlag());

Я обеспокоен новыми экземплярами MyType, указывающими на ту же ссылку для его переменной «data». Поэтому мне нужно полностью скопировать его.

Итак, если у меня есть существующий объект:

MyType someVar = new MyType(someList, false);

// Now, I want a copy of someVar, not another variable pointing to the same reference.

Может ли кто-нибудь указать мне правильное направление?

Ответы [ 5 ]

7 голосов
/ 17 февраля 2010

Первое: в вашем примере кода есть некоторые проблемы с именами: myFlag или someFlag ?

Многие разработчики воздерживаются от Cloneable и просто создают конструктор копирования для класса, когда необходимы глубокие копии:

public class MyType {

   private boolean myFlag;
   private List<Integer> myList;

   public MyType(MyType myInstance) {
      myFlag = myInstance.myFlag;
      myList = new ArrayList<Integer>(myInstance.myList);  
   }
}

Копирование конструкторов довольно распространено, и его можно найти во многих реализациях Collections. Я предпочитаю их внедрению Cloneable для ясности. Также стоит отметить, что даже могущественный Джошуа Блох говорит в Effective Java (второе издание, стр. 61), что конструкторы копирования имеют много преимуществ по сравнению с Cloneable / clone.

  • Они не полагаются на подверженных риску создание внелингвистического объекта механизм
  • Они не требуют неисполнимого соблюдение тонко документированных конвенции
  • Они не конфликтуют с использование последних полей
  • Они не выбрасывают ненужные проверенные Исключения
  • Они не требуют приведения.

Если у вас нет его книги, получите ее !

6 голосов
/ 17 февраля 2010

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

List newData = new ArrayList(data)

Но помните, что в этом случае содержимое списка будет оставаться теми же объектами, поэтому оно не будет настоящей глубокой копией. В вашем случае это Integer с, так что ничего страшного. Но если вы измените его, будьте осторожны.


Если вам нужно клонировать большие графы объектов, то в два этапа:

  1. заставьте ваш класс реализовать интерфейс Serializable
  2. использовать apache commons-lang SerializationUtils.clone(yourObject)

Делает глубокую копию, используя механизмы сериализации в Java.

В качестве альтернативы, вы можете использовать эту библиотеку - она ​​не требует интерфейса Serializable и делает глубокие копии с использованием отражения.

1 голос
/ 17 февраля 2010

Вы должны реализовать Cloneable. Вы определяете, что именно означает «копия вашего типа». Иногда требуется иметь тип, содержащий поле, содержимое которого остается одинаковым в нескольких копиях (== ссылка на один и тот же объект во всех копируемых экземплярах)

Вы должны самостоятельно позаботиться о том, чтобы все поля были фактически скопированы в новый экземпляр. Примитивные типы данных, такие как int, long и т. Д., Копируются по мере их непосредственного хранения, они никогда не содержат ссылок.

Если у вас есть поля для ссылок на объекты какого-либо типа, вам нужно найти механизм для создания копии каждого из них.

Как правило, после вызова .clone() у вас есть мелкая копия. Если (и только если) все типы, используемые в вашем классе, сами правильно реализуют Cloneable, вы получите полностью рекурсивную глубокую копию.

Согласно JavaDoc (Object.clone ()) Clonable означает следующее:

x.clone() != x && x.clone().getClass() == x.getClass() && x.clone().equals(x)

Помните, что это общее намерение , и это не обязательный контракт

0 голосов
/ 17 февраля 2010

ваш класс MyType должен реализовывать Cloneable. тогда вы можете вызвать someVar.clone ()

0 голосов
/ 17 февраля 2010

Реализация ICloneable

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