对象Java的深层副本

Pau*_*aul 5 java clone

我正在尝试克隆MyGraph的一个对象,我希望它是一个深层复制,因此对象内的arraylists也被克隆.现在我有:

public static MyGraph deepCopy(MyGraph G){
    MyGraph Copy = (MyGraph) G.clone();

    Copy.VertexG = (ArrayList<Integer>) G.VertexG.clone();
    Copy.EdgeG = (ArrayList<String>) G.EdgeG.clone();

    return Copy;
}
Run Code Online (Sandbox Code Playgroud)

这会在尝试克隆arraylist时返回错误.我不确定这是否是将arraylists添加到对象的正确方法.

Per*_*ion 3

clone中的操作返回ArrayList对象的浅表副本,并且不适合您的目的。手动解决方法是:

  1. 创建与源列表大小相同的目标数组列表
  2. 迭代源列表并创建每个项目的克隆到目标列表中

clone显然,只有当数组列表包含实现 的项目,并且项目clone操作实际上返回深层副本时,这才有效。换句话说,它不能保证。实际上,为 Java 对象实现深度克隆功能并不容易,请参阅Java 中的广泛讨论:深度克隆/复制实例和其他 SO 线程的推荐解决方案,以了解可用的选项。除了那里提供的答案之外,这里还有一些其他选项:

序列化

如果层次结构中的所有(必需的)对象都可以序列化,那么您可以使用以下简单的代码进行深度克隆:

public MyGraph deepCopy() {
    try {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
        final ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);
        oos.close();

        final ObjectInputStream ois = new ObjectInputStream(
                new ByteArrayInputStream(baos.toByteArray()));
        final MyGraph clone = (QuicksortTest) ois.readObject();
        return clone;
    } catch (final Exception e) {
        throw new RuntimeException("Cloning failed");
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,一些深度克隆库将标准 Java 序列化与反射黑客和/或字节码检测相结合,以使整个对象层次结构完全可序列化。您可能需要,也可能不需要。

复制工具

例如,Dozer,提供快速深度复制功能。Orika也可以实现相同的目的,尽管配置更多:

public MyGraph deepCopy() {
    final DozerBeanMapper mapper = new DozerBeanMapper();
    final QuicksortTest clone = mapper.map(this, MyGraph.class);
    return clone;
}
Run Code Online (Sandbox Code Playgroud)

当然,唯一的缺点是您需要将额外的依赖项引入项目中。

总而言之,你的deepCopy方法应该是静态的。另外,您应该认真考虑通过将对象设为私有并实现 getter/setter 来封装对象的状态。