Вопрос-ответ

How do I copy an object in Java?

Как мне скопировать объект в Java?

Рассмотрим приведенный ниже код:

DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'

DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'

dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'

Итак, я хочу скопировать dum в dumtwo и изменить dum, не затрагивая dumtwo. Но приведенный выше код этого не делает. Когда я что-то меняю в dum, то же самое изменение происходит и в dumtwo.

Я думаю, когда я говорю dumtwo = dum, Java копирует только ссылку. Итак, есть ли какой-нибудь способ создать новую копию dum и назначить ее dumtwo?

Переведено автоматически
Ответ 1

Создайте конструктор копирования:

class DummyBean {
private String dummy;

public DummyBean(DummyBean another) {
this.dummy = another.dummy; // you can access
}
}

У каждого объекта также есть метод clone, который можно использовать для копирования объекта, но не используйте его. Слишком просто создать класс и использовать неподходящий метод clone. Если вы собираетесь это сделать, прочтите хотя бы то, что Джошуа Блох говорит об этом в Эффективной Java .

Ответ 2

Основные: копирование объекта в Java.

Предположим, что существует объект- obj1, который содержит два объекта, containedObj1 и containedObj2.

введите описание изображения здесь

неглубокое копирование:
поверхностное копирование создает новый instance того же класса и копирует все поля в новый экземпляр и возвращает его. Класс Object предоставляет clone метод и обеспечивает поддержку неглубокого копирования.

введите описание изображения здесь

Глубокое копирование:
Глубокое копирование происходит, когда объект копируется вместе с объектами, на которые он ссылается. На рисунке ниже показано, obj1 после того, как с ним было выполнено глубокое копирование. Не только obj1 был скопирован, но и объекты, содержащиеся в нем, также были скопированы. Мы можем использовать Java Object Serialization для создания глубокой копии. К сожалению, у этого подхода тоже есть некоторые проблемы (подробные примеры).

введите описание изображения здесь

Возможные проблемы:

clone сложно реализовать правильно.
Лучше использовать защитное копирование, конструкторы копирования (как отвечает @egaga) или статические фабричные методы.


  1. Если у вас есть объект, который, как вы знаете, имеет открытый clone() метод, но вы не знаете тип объекта во время компиляции, тогда у вас проблема. В Java есть интерфейс, который называется Cloneable. На практике мы должны реализовать этот интерфейс, если хотим создать объект Cloneable. Object.clone он защищен, поэтому мы должны переопределить его с помощью открытого метода, чтобы он был доступен.

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

Например, org.apache.commons.lang.SerializationUtils будет иметь метод для глубокого клонирования с использованием сериализации (исходный код). Если нам нужно клонировать Bean, то в org.apache.commons.beanutils есть пара служебных методов (Исходный код).


  • cloneBean будет клонировать компонент на основе доступных методов получения и установки свойств, даже если сам класс bean не реализует Cloneable.

  • copyProperties скопирует значения свойств из исходного компонента в конечный компонент для всех случаев, когда имена свойств совпадают.

Ответ 3

В пакете import org.apache.commons.lang.SerializationUtils; есть метод:

SerializationUtils.clone(Object);

Пример:

this.myObjectCloned = SerializationUtils.clone(this.object);
Ответ 4

Просто следуйте приведенным ниже инструкциям:

public class Deletable implements Cloneable{

private String str;
public Deletable(){
}
public void setStr(String str){
this.str = str;
}
public void display(){
System.out.println("The String is "+str);
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

и везде, где вы хотите получить другой объект, просто выполните клонирование.
например:

Deletable del = new Deletable();
Deletable delTemp = (Deletable ) del.clone(); // this line will return you an independent
// object, the changes made to this object will
// not be reflected to other object
java