考虑下面的代码:

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'

所以,我想把dumm复制到dum2,在不影响dum2的情况下改变dumm。但是上面的代码并没有这样做。当我改变了dumm中的一些东西,同样的变化也会发生在dum2中。

我想,当我说dumtwo = dum时,Java只复制了引用。那么,有没有办法创建一个新的dum副本并将其分配给dumtwo呢?


当前回答

这里有一个关于clone()的合理解释,如果你最终需要它…

这里:克隆(Java方法)

其他回答

public class MyClass implements Cloneable {

private boolean myField= false;
// and other fields or objects

public MyClass (){}

@Override
public MyClass clone() throws CloneNotSupportedException {
   try
   {
       MyClass clonedMyClass = (MyClass)super.clone();
       // if you have custom object, then you need create a new one in here
       return clonedMyClass ;
   } catch (CloneNotSupportedException e) {
       e.printStackTrace();
       return new MyClass();
   }

  }
}

在你的代码中:

MyClass myClass = new MyClass();
// do some work with this object
MyClass clonedMyClass = myClass.clone();

使用gson复制对象。

public static <T>T copyObject(Object object){
    Gson gson = new Gson();
    JsonObject jsonObject = gson.toJsonTree(object).getAsJsonObject();
    return gson.fromJson(jsonObject,(Type) object.getClass());
}

假设我有一个客体人。所以

Person copyPerson = copyObject(person);

注意:性能要慢得多。

替代egaga的构造函数复制方法。您可能已经有了一个POJO,因此只需添加另一个方法copy(),该方法返回初始化对象的副本。

class DummyBean {
    private String dummyStr;
    private int dummyInt;

    public DummyBean(String dummyStr, int dummyInt) {
        this.dummyStr = dummyStr;
        this.dummyInt = dummyInt;
    }

    public DummyBean copy() {
        return new DummyBean(dummyStr, dummyInt);
    }

    //... Getters & Setters
}

如果你已经有一个DummyBean,想要一个副本:

DummyBean bean1 = new DummyBean("peet", 2);
DummyBean bean2 = bean1.copy(); // <-- Create copy of bean1 

System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());

//Change bean1
bean1.setDummyStr("koos");
bean1.setDummyInt(88);

System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());

输出: Bean1:宠物2 Bean2: peet 2 豆1:库斯88 Bean2: peet 2

但两者都很好,最终取决于你……

基本:Java对象复制。

让我们假设一个对象——obj1,它包含两个对象,containedObj1和containedObj2。

浅复制: 浅复制创建同一个类的新实例,并将所有字段复制到新实例并返回它。类提供了克隆方法,并提供了对浅复制的支持。

深复制: 当对象与其引用的对象一起复制时,就会发生深度复制。下图显示obj1在深度复制后被执行。不仅obj1被复制了,它包含的对象也被复制了。我们可以使用Java对象序列化来进行深度复制。不幸的是,这种方法也有一些问题(详细的示例)。

可能的问题: 克隆是很难正确实现的。 最好使用防御性复制、复制构造函数(如@egaga reply)或静态工厂方法。

If you have an object, that you know has a public clone() method, but you don’t know the type of the object at compile time, then you have problem. Java has an interface called Cloneable. In practice, we should implement this interface if we want to make an object Cloneable. Object.clone is protected, so we must override it with a public method in order for it to be accessible. Another problem arises when we try deep copying of a complex object. Assume that the clone() method of all member object variables also does deep copy, this is too risky of an assumption. You must control the code in all classes.

例如,org.apache.commons.lang.SerializationUtils将有使用序列化进行深度克隆的方法(源代码)。如果我们需要克隆Bean,那么在org.apache.commons.beanutils (Source)中有两个实用程序方法。

cloneBean将基于可用的属性getter和setter克隆一个bean,即使bean类本身没有实现Cloneable。 copyProperties将在所有属性名称相同的情况下,将属性值从源bean复制到目标bean。

class DB {
  private String dummy;

  public DB(DB one) {
    this.dummy = one.dummy; 
  }
}