考虑下面的代码:

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呢?


当前回答

深度克隆是您的答案,它需要实现Cloneable接口并重写clone()方法。

public class DummyBean implements Cloneable {

   private String dummy;

   public void setDummy(String dummy) {
      this.dummy = dummy;
   }

   public String getDummy() {
      return dummy;
   }

   @Override
   public Object clone() throws CloneNotSupportedException {
      DummyBean cloned = (DummyBean)super.clone();
      cloned.setDummy(cloned.getDummy());
      // the above is applicable in case of primitive member types like String 
      // however, in case of non primitive types
      // cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
      return cloned;
   }
}

你会这样称呼它 DummyBean dumtwo = dumm .clone();

其他回答

我使用谷歌的JSON库来序列化它,然后创建序列化对象的新实例。它进行深度复制,但有一些限制:

不能有任何递归引用 它不会复制不同类型的数组 数组和列表应该被类型化,否则它将找不到要实例化的类 您可能需要在自己声明的类中封装字符串

我还使用这个类来保存用户首选项,窗口和在运行时重新加载的东西。这是非常容易使用和有效的。

import com.google.gson.*;

public class SerialUtils {

//___________________________________________________________________________________

public static String serializeObject(Object o) {
    Gson gson = new Gson();
    String serializedObject = gson.toJson(o);
    return serializedObject;
}
//___________________________________________________________________________________

public static Object unserializeObject(String s, Object o){
    Gson gson = new Gson();
    Object object = gson.fromJson(s, o.getClass());
    return object;
}
       //___________________________________________________________________________________
public static Object cloneObject(Object o){
    String s = serializeObject(o);
    Object object = unserializeObject(s,o);
    return object;
}
}

使用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);

注意:性能要慢得多。

您可以尝试实现Cloneable并使用clone()方法;但是,如果你使用clone方法,你应该——按照标准——总是覆盖Object的公共Object clone()方法。

要做到这一点,你必须以某种方式克隆对象。虽然Java有克隆机制,但如果没有必要就不要使用它。创建一个复制方法,为你做复制工作,然后做:

dumtwo = dum.copy();

这里有一些关于完成副本的不同技巧的建议。

替代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

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