Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 深度克隆实用程序推荐_Java_Clone - Fatal编程技术网

Java 深度克隆实用程序推荐

Java 深度克隆实用程序推荐,java,clone,Java,Clone,是否有针对java集合的深度克隆实用程序: 阵列 列表 地图 注意:首选一些不使用序列化,但使用Object.clone()方法的解决方案。我可以确定我的自定义对象将实现clone()方法,并且只使用可克隆的java标准类…深入克隆任意集合的一种常用方法是将其序列化为流,然后将其读回新的集合。您将重新水化与旧对象没有任何关系的全新对象,而不是相同的副本 查看布鲁诺的答案,以获得指向的链接,如果这是您决定采取的路线,这将非常有用。一种可能性是使用序列化: ApacheCommons提供了使用序

是否有针对java集合的深度克隆实用程序:

  • 阵列
  • 列表
  • 地图

注意:首选一些不使用序列化,但使用Object.clone()方法的解决方案。我可以确定我的自定义对象将实现clone()方法,并且只使用可克隆的java标准类…

深入克隆任意集合的一种常用方法是将其序列化为流,然后将其读回新的集合。您将重新水化与旧对象没有任何关系的全新对象,而不是相同的副本


查看布鲁诺的答案,以获得指向的链接,如果这是您决定采取的路线,这将非常有用。

一种可能性是使用序列化


ApacheCommons提供了使用序列化然后反序列化,但是请注意,这种方法只适用于没有临时字段的可序列化类。此外,您的单例将不再是单例。

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

克隆

  • clone()方法受保护,因此除非相关类使用公共方法重写它,否则不能直接调用它
  • clone()不调用构造函数。任何构造函数。它将分配内存、分配内部
    字段(您可以通过
    getClass()
    读取该字段)并复制原始文件的字段
  • 有关clone()的更多问题,请参阅Joshua Bloch书中的第11项“”

    序列化

    连载更糟糕;它有许多
    clone()
    的缺陷,还有一些缺陷。约书亚有一整章,仅就这个主题就有四个项目

    我的解决方案

    我的解决方案是向我的项目添加新接口:

    public interface Copyable<T> {
        T copy ();
        T createForCopy ();
        void copyTo (T dest);
    }
    
    公共接口可复制{
    T拷贝();
    T createForCopy();
    无效副本(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...
        }
    }
    
    类演示实现了可复制{
    公开演示副本(){
    Demo copy=createForCopy();
    抄送(复印);
    返回副本;
    }
    公共演示createForCopy(){
    返回新的Demo();
    }
    公共作废副本(演示目的地)
    super.copyTo(dest);
    …在此处复制演示的字段。。。
    }
    }
    
    不幸的是,我必须将此代码复制到我的所有对象,但它始终是相同的代码,因此我可以使用Eclipse编辑器模板。优点:

  • 我可以决定调用哪个构造函数以及如何初始化哪个字段
  • 初始化按确定性顺序进行(根类到实例类)
  • 我可以重用现有对象并覆盖它们
  • 类型安全
  • 单身人士继续单身

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

    我认为前面的绿色答案不好,你为什么会问

    • 它添加了很多代码
    • 它要求您列出要复制的所有字段并执行此操作
    • 当使用clone()时,这不适用于列表 (这就是HashMap的clone()所说的:返回此HashMap实例的浅拷贝:未克隆密钥和值本身。)因此,您最终手动执行了此操作(这让我哭哭啼啼)
    哦,顺便说一句,序列化也很糟糕,你可能不得不到处添加Serializable(这也让我哭了)

    那么解决方案是什么:

    Java深度克隆库 克隆库是一个小型的开源(apache许可证)java库,用于深度克隆对象。对象不必实现可克隆接口。这个库可以有效地克隆任何java对象。如果您不希望修改缓存对象,或者希望创建对象的深度副本,则可以在缓存实现中使用它

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

    请访问

    浅层克隆一个集合很容易,但如果您想进行深度克隆,库可能比手工编码更好(因为您还想克隆集合中的元素)

    就像,我使用了,并针对XStream(可以通过序列化然后反序列化来“克隆”)和二进制序列化对其进行了性能测试。虽然XStream在序列化到xml或从xml序列化方面非常快,但Cloner在克隆方面要快得多:

    0.0851 ms:xstream(通过序列化/反序列化进行克隆)
    0.0223毫秒:二进制序列化(通过序列化/反序列化进行克隆)
    0.0017毫秒:克隆器
    *克隆简单对象(两个字段)和无默认公共构造函数的平均时间。跑10000次

    除了速度快之外,选择cloner的原因还有:

  • 对任何对象(即使不是自己编写的对象)执行深度克隆
  • 不必每次添加字段时都使clone()方法保持最新
  • 可以克隆没有默认公共构造函数的对象
  • 与Spring一起工作
  • (优化)不克隆已知的不可变对象(如整数、字符串等)
  • 易于使用。例如:

    cloner.deepClone(anyObject)


  • 我是克隆人库的创造者,布拉德提出的克隆人库。这是一种克隆对象的解决方案,无需编写任何额外代码(无需序列化对象或impl clone()方法)

    正如Brad所说,速度非常快,最近我上传了一个更快的版本。请注意,手动实现clone()方法将比clone lib更快,但同样需要编写大量代码

    Cloner lib对我来说工作得很好,因为我在一个流量非常大的站点(每天约100万个请求)的缓存实现中使用它。缓存应为每个请求克隆大约10个对象。它是相当可靠和稳定的。但是ple
    public class CloneMePlease {
        @Clone(Skip.class)
        String id3 = UUID.randomUUID().toString();
    
        @Clone(Null.class)
        String id4 = UUID.randomUUID().toString();
    
        @Clone(value = RandomUUID.class, groups=CustomActivationGroup1.class)
        String id5 = UUID.randomUUID().toString();
    
        @Clone.List({
                @Clone(groups=CustomActivationGroup2.class, value=Skip.class),
                @Clone(groups=CustomActivationGroup3.class, value=Copy.class)})
        Object activationGroupOrderTest = new Object();
    
        @Clone(LongIncrement.class)
        long version = 1l;
    
        @PostClone
        private void postClone(CloneMePlease original, @CloneInject CloneInjectedService service){
             //do stuff with the original source object in the context of the cloned object
             //you can inject whatewer service you want, from spring/guice to perform custom logic here
        }
    }