深度克隆实用程序建议 [已关闭]

2022-08-31 13:09:54

有没有用于Java集合的深度克隆的实用程序:

  • 阵 列
  • 列表
  • 地图

注意:更喜欢一些不使用序列化的解决方案,而是使用Object.clone()方法。我可以肯定我的自定义对象将实现 clone() 方法,并且将仅使用可克隆的 java 标准类...


答案 1

我认为之前的绿色答案很糟糕,为什么你会问?

  • 它添加了很多代码
  • 它要求您列出要复制的所有字段并执行此操作
  • 当使用 clone() 时,这对 Lists 不起作用(这就是 HashMap 的 clone() 所说的:返回此 HashMap 实例的浅层副本:键和值本身未克隆)。因此您最终手动执行此操作(这让我哭泣)

哦,顺便说一句,序列化也很糟糕,你可能不得不到处添加Serializable(这也让我哭了)。

那么解决方案是什么:

Java Deep-Cloning库 克隆库是一个小型的开源(apache许可证)java库,用于深度克隆对象。对象不必实现可克隆接口。实际上,这个库可以克隆任何java对象。例如,如果您不希望修改缓存的对象,或者每当您想要创建对象的深层副本时,都可以使用它。

Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);

查看 https://github.com/kostaskougios/cloning


答案 2

在Java中复制对象的所有方法都有严重的缺陷:

克隆

  1. clone() 方法受到保护,因此您不能直接调用它,除非有问题的类使用公共方法覆盖它。
  2. clone() 不调用构造函数。任何构造函数。它将分配内存,分配内部字段(您可以通过)并复制原始字段。classgetClass()

有关 clone() 的更多问题,请参阅 Joshua Bloch 的书“Effective Java, Second Edition”的第 11 项。"

序列 化

序列化甚至更糟;它有许多缺陷,然后是一些。约书亚有一整章,仅这个主题就有四个项目。clone()

我的解决方案

我的解决方案是向我的项目添加一个新界面:

public interface Copyable<T> {
    T copy ();
    T createForCopy ();
    void copyTo (T dest);
}

代码如下所示:

class Demo implements Copyable<Demo> {
    public Demo copy () {
        Demo copy = createForCopy ();
        copyTo (copy);
        return copy;
    }
    public Demo createForCopy () {
        return new Demo ();
    }
    public void copyTo (Demo dest)
        super.copyTo (dest);
        ...copy fields of Demo here...
    }
}

不幸的是,我必须将此代码复制到我的所有对象中,但它始终是相同的代码,因此我可以使用Eclipse编辑器模板。优势:

  1. 我可以决定调用哪个构造函数以及如何初始化哪个字段。
  2. 初始化按确定性顺序进行(根类到实例类)
  3. 我可以重用现有对象并覆盖它们
  4. 类型安全
  5. 单例停留单例

对于标准的Java类型(如集合等),我使用一个可以复制这些类型的实用程序类。这些方法具有标志和回调,因此我可以控制副本的深度。