如何在Java中复制对象?

如何在Java中复制对象?,java,object,copy,clone,Java,Object,Copy,Clone,考虑以下代码: 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

考虑以下代码:

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
复制到
dumtoo
并在不影响
dumtoo
的情况下更改
dum
。但上面的代码并没有这样做。当我在
dum
中更改某些内容时,在
dumtoo
中也会发生相同的更改


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

要做到这一点,您必须以某种方式克隆对象。尽管Java有一种克隆机制,但如果不需要,就不要使用它。创建一个为您执行复制工作的复制方法,然后执行以下操作:

dumtwo = dum.copy();

这是一些关于复制不同技巧的更多建议。

是的。您需要保存您的对象。

如果您最终需要克隆(),这里有一个不错的解释


创建一个复制构造函数:

class DummyBean {
  private String dummy;

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

每个对象都有一个克隆方法,可以用来复制对象,但不要使用它。创建类和执行不正确的克隆方法太容易了。如果你要这么做,至少要读一读约书亚·布洛赫在书中对它所说的话。

是的,你只是在引用这个对象。如果对象实现了
Cloneable
,则可以克隆该对象

查看这篇关于复制对象的wiki文章


除了显式复制,另一种方法是使对象不可变(no
set
或其他mutator方法)。这样,问题就永远不会出现。对于较大的对象,不变性变得更加困难,但另一方面,它将您推向分裂成连贯的小对象和组合的方向。

您可以尝试实现
Cloneable
并使用
clone()
方法;但是,如果使用克隆方法,按照标准,您应该始终覆盖
对象的
公共对象克隆()
方法。

如下所示:

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();
    }
}
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;
   }
}
无论您想在哪里获得另一个对象,都可以执行简单的克隆。 e、 g:


您可以使用XStream从以下位置自动进行深度复制:

XStream是一个简单的库,用于将对象序列化为XML并返回 再说一遍

将其添加到项目中(如果使用maven)


这样,您就可以获得一个拷贝,而无需实现任何克隆接口。

使用深度克隆实用程序:

SomeObjectType copy = new Cloner().deepClone(someObject);

这将深度复制任何java对象,请在

基本:java中的对象复制中查看它。

让我们假设一个对象-
obj1
,它包含两个对象,containedObj1containedObj2

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

深度复制:
当对象与其引用的对象一起复制时,会发生深度复制。下图显示了对obj1执行深度复制后的
obj1
。不仅复制了
obj1
,而且还复制了其中包含的对象。我们可以使用
Java对象序列化
制作深度拷贝。不幸的是,这种方法也有一些问题()

可能的问题:
克隆
很难正确实施。
最好使用(如@egaga reply)或。

  • 如果您有一个对象,您知道它有一个public
    clone()
    方法,但在编译时您不知道对象的类型,那么您就有问题了。Java有一个名为
    Cloneable
    的接口。实际上,如果我们想使对象
    可克隆
    ,就应该实现这个接口<代码>对象。克隆
  • 受保护
    ,因此我们必须使用公共方法覆盖它,以使其可访问。
  • 当我们尝试对复杂对象进行深度复制时,会出现另一个问题。假设所有成员对象变量的
    clone()
    方法也进行深度复制,这一假设风险太大。您必须控制所有类中的代码。
  • 例如,将使用serialization()创建深度克隆的方法。如果我们需要克隆Bean,那么()中有两个实用程序方法

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

    在包
    中导入org.apache.commons.lang.SerializationUtils有一种方法:

    SerializationUtils.clone(Object);
    
    例如:

    this.myObjectCloned = SerializationUtils.clone(this.object);
    

    我使用Google的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;
    }
    }
    

    Cloneable
    和下面的代码添加到类中

    public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    

    使用这个
    clonedObject=(YourClass)yourClassObject.clone()

    深度克隆是您的答案,它需要实现
    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 dumtowo=dum.clone()

    为什么使用反射API没有答案

    private static Object cloneObject(Object obj){
            try{
                Object clone = obj.getClass().newInstance();
                for (Field field : obj.getClass().getDeclaredFields()) {
                    field.setAccessible(true);
                    field.set(clone, field.get(obj));
                }
                return clone;
            }catch(Exception e){
                return null;
            }
        }
    
    是你
    class DB {
      private String dummy;
    
      public DB(DB one) {
        this.dummy = one.dummy; 
      }
    }
    
    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;
       }
    }
    
    private static Object cloneObject(Object obj){
            try{
                Object clone = obj.getClass().newInstance();
                for (Field field : obj.getClass().getDeclaredFields()) {
                    field.setAccessible(true);
                    field.set(clone, field.get(obj));
                }
                return clone;
            }catch(Exception e){
                return null;
            }
        }
    
    private static Object cloneObject(Object obj){
            try{
                Object clone = obj.getClass().newInstance();
                for (Field field : obj.getClass().getDeclaredFields()) {
                    field.setAccessible(true);
                    if(field.get(obj) == null || Modifier.isFinal(field.getModifiers())){
                        continue;
                    }
                    if(field.getType().isPrimitive() || field.getType().equals(String.class)
                            || field.getType().getSuperclass().equals(Number.class)
                            || field.getType().equals(Boolean.class)){
                        field.set(clone, field.get(obj));
                    }else{
                        Object childObj = field.get(obj);
                        if(childObj == obj){
                            field.set(clone, clone);
                        }else{
                            field.set(clone, cloneObject(field.get(obj)));
                        }
                    }
                }
                return clone;
            }catch(Exception e){
                return null;
            }
        }
    
    private Object copyObject(Object objSource) {
            try {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(objSource);
                oos.flush();
                oos.close();
                bos.close();
                byte[] byteData = bos.toByteArray();
                ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
                try {
                    objDest = new ObjectInputStream(bais).readObject();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return objDest;
    
        }
    
    class UserAccount{
       public int id;
       public String name;
    }
    
    Gson gson = new Gson();
    updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);
    
    class UserAccount{
            public int id;
            public String name;
            //empty constructor
            public UserAccount(){}
            //parameterize constructor
            public UserAccount(int id, String name) {
                this.id = id;
                this.name = name;
            }
    
            //copy constructor
            public UserAccount(UserAccount in){
                this(in.id,in.name);
            }
        }
    
    import net.zerobuilder.BeanBuilder
    
    @BeanBuilder
    public class DummyBean { 
      // bean stuff
    }
    
    DummyBean bean = new DummyBean();
    // Call some setters ...
    // Now make a copy
    DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done();
    
    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();
    
    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 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: peet 2
    bean2: peet 2
    
    bean1: koos 88
    bean2: peet 2
    
    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);
    
    fun <T : Any?> T.duplicate(): T? {
        var copyObject: T? = null
        try {
            val byteArrayOutputStream = ByteArrayOutputStream()
            val objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
            objectOutputStream.writeObject(this)
            objectOutputStream.flush()
            objectOutputStream.close()
            byteArrayOutputStream.close()
            val byteData = byteArrayOutputStream.toByteArray()
            val byteArrayInputStream = ByteArrayInputStream(byteData)
            try {
                copyObject = ObjectInputStream(byteArrayInputStream).readObject() as T
            } catch (e: ClassNotFoundException) {
                e.printStackTrace()
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return copyObject
    }
    
    var object = Any()
    var duplicateObject = object.duplicate()
    
    <T extends Object> T copyObject(T sourceObject) {
    
        T copyObject = null;
    
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(sourceObject);
            objectOutputStream.flush();
            objectOutputStream.close();
            byteArrayOutputStream.close();
            byte[] byteData = byteArrayOutputStream.toByteArray();
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteData);
            try {
                copyObject = (T) new ObjectInputStream(byteArrayInputStream).readObject();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return copyObject;
    }
    
    Object object = new Object();
    Object duplicateObject = copyObject(object);