当前位置:  开发笔记 > 编程语言 > 正文

Deep clone实用程序推荐

如何解决《Deepclone实用程序推荐》经验,为你挑选了6个好方法。

是否有任何用于深度克隆java集合的实用程序:

数组

清单

地图

注意:在不使用序列化的情况下更喜欢某些解决方案,但使用Object.clone()方法.我可以肯定我的自定义对象将实现clone()方法,并将只使用可克隆的java标准类...



1> Cojones..:

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

它增加了很多代码

它要求您列出要复制的所有字段并执行此操作

当使用clone()时,这对于列表不起作用(这是HashMap的clone()所说的:返回此HashMap实例的浅表副本:键和值自身未被克隆.)所以你最终手动完成它(这使得我哭了)

哦顺便说一下序列化也很糟糕,你可能不得不在整个地方添加Serializable(这也让我哭).

那么解决方案是什么:

Java深度 克隆库克隆库是一个小型的开源(apache许可证)java库,它深入克隆对象.对象不必实现Cloneable接口.实际上,这个库可以克隆任何java对象.如果您不希望修改缓存对象或者只是想要创建对象的深层副本,则可以在缓存实现中使用它.

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

请访问https://github.com/kostaskougios/cloning查看


Cloner是一个很棒的图书馆(只有它的表现有时让我哭...但我猜你用反射做得不够好)

2> Aaron Digull..:

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

克隆

    clone()方法受到保护,因此除非有问题的类使用公共方法覆盖它,否则无法直接调用它.

    clone()不会调用构造函数.任何构造函数.它将分配内存,分配内部class字段(您可以通过其读取getClass())并复制原始字段.

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

连载

序列化更糟糕; 它有许多缺点,clone()然后有一些缺陷.约书亚有一整章只有四个项目.

我的解决方案

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

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

代码如下所示:

class Demo implements Copyable {
    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编辑器模板.好处:

    我可以决定调用哪个构造函数以及如何初始化哪个字段.

    初始化以确定性顺序发生(根类到实例类)

    我可以重用现有的对象并覆盖它们

    输入安全

    单身人士留着单身人士

对于标准Java类型(如集合等),我使用可以复制它们的实用程序类.这些方法有标记和回调,所以我可以控制副本的深度.


我通过在我需要克隆的所有类中实现clone()来做类似的事情.最大的问题是,如果我有收藏品,我必须迭代它并由我自己复制它...

3> Brad Cupit..:

浅克隆的集合是很容易的,但如果你想深克隆,图书馆可能会做你比手更好的编码它(因为要克隆的元素里面集合为好).

就像这个答案一样,我使用了Cloner库,并专门针对XStream进行了性能测试(可以通过序列化然后反序列化来克隆')和二进制序列化.虽然XStream在向/从xml序列化方面非常快,但克隆在克隆方面要快得多:

0.0851 ms:xstream(通过序列化/反
序列化克隆)0.0223 ms:二进制序列化(通过序列化/反序列化克隆)
0.0017 ms:cloner
*克隆一个简单对象(两个字段)的平均时间,没有默认的公共构造函数.运行10,000次.

除了快速,这里有更多选择克隆人的理由:

    执行任何对象的深度克隆(即使是那些你自己不写的对象)

    每次添加字段时,都不必使clone()方法保持最新

    您可以克隆没有默认公共构造函数的对象

    适用于Spring

    (优化)不克隆已知的不可变对象(如Integer,String等)

    使用方便.例:

    cloner.deepClone(anyObject);



4> 小智..:

我是克隆人提出的克隆人lib的创造者.这是一个克隆对象的解决方案,无需编写任何额外的代码(不需要可序列化的对象或impl clone()方法)

布拉德说,这是非常快的,最近我上传了一个更快的版本.请注意,手动实现clone()方法将比克隆lib更快,但是您需要再次编写大量代码.

Cloner lib对我来说效果很好,因为我在一个缓存实现中使用它来处理流量非常大的站点(每天约100万个请求).缓存应该每个请求克隆大约10个对象.它非常可靠和稳定.但请注意克隆并非没有风险.可以将lib配置为打印在dev期间克隆的每个类实例.通过这种方式,您可以检查它是否克隆了您认为应该克隆的内容 - 对象图可以非常深,并且可以包含对大量对象的引用.使用clone lib,您可以指示它不克隆您不需要的对象,即单例.



5> John Feminel..:

深度克隆任意集合的一种通用方法是将其序列化为流,然后将其读回新集合.除了是相同的副本之外,你将完全重新水化与旧的没有任何关系的新对象.

查看Bruno的答案,获取Apache Commons序列化实用程序类的链接,如果这是您决定采用的路线,这将非常有用.



6> bruno conde..:

一种可能性是使用序列化:

Apache Commons提供SerializationUtils

推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有