实现深度对象复制函数有点困难。您采取什么步骤来确保原始对象和克隆对象没有共享引用?


当前回答

这是一个关于如何深度克隆任何对象的简单示例: 首先实现serializable

public class CSVTable implements Serializable{
    Table<Integer, Integer, String> table; 
    public CSVTable() {
        this.table = HashBasedTable.create();
    }
    
    public CSVTable deepClone() {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(this);

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            return (CSVTable) ois.readObject();
        } catch (IOException e) {
            return null;
        } catch (ClassNotFoundException e) {
            return null;
        }
    }

}

然后

CSVTable table = new CSVTable();
CSVTable tempTable = table.deepClone();

才能得到克隆体。

其他回答

一个非常快速和简单的一行程序解决方案是使用Jackson。

看一下示例代码片段:

ObjectMapper objectMapper = new ObjectMapper();

MyClass deepCopyObject = objectMapper
  .readValue(objectMapper.writeValueAsString(originalObject), MyClass.class);

在上面的例子中:“MyClass”指的是你想要复制的对象的类。

解释:我们只是试图将原始对象序列化为字符串,然后将字符串反序列化回对象,从而获得一个深度副本。 了解更多关于ObjectMapper的信息,请访问:https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/ObjectMapper.html

XStream在这种情况下非常有用。这是一个简单的代码来做克隆

private static final XStream XSTREAM = new XStream();
...

Object newObject = XSTREAM.fromXML(XSTREAM.toXML(obj));

BeanUtils在深度克隆bean方面做得非常好。

BeanUtils.cloneBean(obj);

1)

public static Object deepClone(Object object) {
   try {
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     ObjectOutputStream oos = new ObjectOutputStream(baos);
     oos.writeObject(object);
     ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
     ObjectInputStream ois = new ObjectInputStream(bais);
     return ois.readObject();
   }
   catch (Exception e) {
     e.printStackTrace();
     return null;
   }
 }

2)

    // (1) create a MyPerson object named Al
    MyAddress address = new MyAddress("Vishrantwadi ", "Pune", "India");
    MyPerson al = new MyPerson("Al", "Arun", address);

    // (2) make a deep clone of Al
    MyPerson neighbor = (MyPerson)deepClone(al);

这里,您的MyPerson和MyAddress类必须实现可序列化接口

一些人提到了使用或重写Object.clone()。不要这样做。Object.clone()存在一些主要问题,在大多数情况下不鼓励使用它。请参见Joshua Bloch的“Effective Java”中的第11项,以获得完整的答案。我相信您可以安全地在基本类型数组上使用Object.clone(),但除此之外,您还需要明智地正确使用和重写clone。

依赖于序列化(XML或其他方式)的方案是拙劣的。

这个问题没有简单的答案。如果你想要深度复制一个对象,你必须遍历对象图,并通过对象的复制构造函数或静态工厂方法显式复制每个子对象,然后再深度复制子对象。不需要复制不可变对象(例如字符串)。顺便说一句,出于这个原因,您应该支持不可变性。