精华内容
下载资源
问答
  • 主要介绍了Java中的深拷贝(深复制)和浅拷贝(浅复制)介绍,需要的朋友可以参考下
  • 如果要实现深复制,通过有几种做法,可以用foreach, 或者重写Clone()方法。 但最好用和最方便的方法还是使用【序列化】的方式来实现。 序列化是指将对象转换为字节流的形式,然后保存在内存或者数据库中
  • java反射机制创建对象实现:java 深度拷贝 -超完美,只使反射机制,不使用其它封装好的深度拷贝的工具类
  • java List 深度复制方法

    2019-04-26 01:11:41
    NULL 博文链接:https://bijian1013.iteye.com/blog/2358367
  • java深度复制源代码

    2017-01-22 16:32:28
    深度复制,赋值后给新对象赋值不会影响原始对象。
  • 接下来,我们看下这几种方法的效率和源码,以及如何使用序列化和反序列化实现组合类的深复制。 我们以百万级和千万级的数据作为测试集。测试源码如下: public static void main(String[] args) throws ...
  • 主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下
  • 浅复制与深复制只存在于引用数据类型当中 基本数据类型储存在栈内存当中 栈内存是一个萝卜一个坑 互不影响 引用数据类型储存在堆内存当中 堆内存是一片储存空间,引用数据类型存储在堆内存中的是一个内存地址 ,...
  • 当年也是纠结于深复制和浅复制,这里很详细的见解了下
  • Fastjson JSONObject深度复制

    千次阅读 2021-02-24 22:16:54
    Fastjson JSONObject深度复制 如何对fajstjson JSONObject类型的数据进行深度复制,有几种方式呢? 1,new JSONObject (Object) - 失败 代码: public static void main(String[] args) throws ...

    Fastjson JSONObject深度复制

    目录

    Fastjson JSONObject深度复制

    1,new JSONObject (Object) - 失败

    2,Put All;

    3,串行化复制;

    总结:


    如何对fajstjson JSONObject类型的数据进行深度复制,有几种方式呢?

     

    1,new JSONObject (Object) - 失败

     

    代码:

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        testNewJson();
    }
    
    public static void testNewJson(){
        System.out.println("====== new JSONObject fail =======");
        JSONObject one = new JSONObject();
        one.put("one","fish");
        JSONObject two = new JSONObject(one);
        System.out.println("init: one: "+ one.toString());
        System.out.println("init: two: "+ two.toString());
        System.out.println("====== add grass =======");
        two.put("two","grass");
        System.out.println("change: one: "+ one.toString());
        System.out.println("change: two: "+ two.toString());
        System.out.println("====== new JSONObject fail =======");
    }

     

    结果:

    ====== new JSONObject fail =======
    
    init: one: {"one":"fish"}
    
    init: two: {"one":"fish"}
    
    ====== add grass =======
    
    change: one: {"one":"fish","two":"grass"}
    
    change: two: {"one":"fish","two":"grass"}
    
    ====== new JSONObject fail =======

    new JSONObject(one) 这种方式失败了 new JSONObject(Object)深复制失败的原因​​​​​​​

    2,Put All;

    代码:

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        testPutAllJson();
    }
    
    public static void testPutAllJson(){
        System.out.println("====== put all =======");
        JSONObject one = new JSONObject();
        one.put("one","fish");
        JSONObject two = new JSONObject();
        two.putAll(one);
        System.out.println("init: one: "+ one.toString());
        System.out.println("init: two: "+ two.toString());
        System.out.println("====== add fox =======");
        two.put("two","fox");
        System.out.println("change: one: "+ one.toString());
        System.out.println("change: two: "+ two.toString());
        System.out.println();
    }
    
    

    结果:

    ====== put all =======
    
    init: one: {"one":"fish"}
    
    init: two: {"one":"fish"}
    
    ====== add fox =======
    
    change: one: {"one":"fish"}
    
    change: two: {"one":"fish","two":"fox"}

     putAll的方式行得通

     

    3,串行化复制;

     

    代码:

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        testDeppCopyJson();
    }
    
    public static void testDeppCopyJson() throws IOException, ClassNotFoundException {
        System.out.println("====== serializable success =======");
        JSONObject one = new JSONObject();
        one.put("one","fish");
        JSONObject two =  CloneUtils.clone(one);
        two.putAll(one);
        System.out.println("init: one: "+ one.toString());
        System.out.println("init: two: "+ two.toString());
        System.out.println("====== add wolf =======");
        two.put("two","wolf");
        System.out.println("change: one: "+ one.toString());
        System.out.println("change: two: "+ two.toString());
        System.out.println();
    }

     

    串行化代码:

    public class CloneUtils {
    
        public static <T extends Serializable> T clone(T src) throws IOException, ClassNotFoundException {
            ObjectInputStream ois = getInputStream(src);
            //返回生成的新对象
            @SuppressWarnings("unchecked")
            T cloneObj = (T) ois.readObject();
            ois.close();
            return cloneObj;
    
        }
    
        public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
            ObjectInputStream ois = getInputStream(src);
            @SuppressWarnings("unchecked")
            List<T> dest = (List<T>) ois.readObject();
            ois.close();
            return dest;
        }
     
        public static <K,V> Map<K,V> cloneMap(Map<K,V> src) throws IOException, ClassNotFoundException {
            ObjectInputStream ois = getInputStream(src);
            @SuppressWarnings("unchecked")
            Map<K, V> result =   (Map<K, V>)     ois.readObject();
            ois.close();
            return result;
    
        }
    
        private static ObjectInputStream getInputStream(Object src) throws IOException, ClassNotFoundException {
            //写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream obs = new ObjectOutputStream(out);
            obs.writeObject(src);
            obs.close();
            //分配内存,写入原始对象,生成新对象
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
            return new ObjectInputStream(ios);
        }
    }

     

    结果:

    ====== serializable success =======
    
    init: one: {"one":"fish"}
    
    init: two: {"one":"fish"}
    
    ====== add wolf =======
    
    change: one: {"one":"fish"}
    
    change: two: {"one":"fish","two":"wolf"}

     

    总结:

       在使用fastjon JSONObject复制的时候,一般用第二种putAll的方式,如果大量使用,也可以考虑用第三种方式。

     

     

    展开全文
  • C++对象的浅复制和深复制详解及简单实例 浅复制:两个对象复制完成后共享某些资源(内存),其中一个对象的销毁会影响另一个对象 深复制:两个对象复制完成后不会共享任何资源,其中一个对象的销毁不会影响另一个...
  • javascript中的深复制 JavaScript深拷贝是初学者甚至有经验的开发着,都会经常遇到问题,并不能很好的理解javascript的深拷贝。  深拷贝(deepClone)是神马,与深拷贝相对应的就是浅拷贝,刚开始我也没弄懂。  在很...
  • 该模块非常简单,只提供了两个主要的方法: copy.copy 与 copy.deepcopy ,分别表示浅复制与深复制。什么是浅复制,什么是深复制,网上有一卡车一卡车的资料,这里不作详细介绍。复制操作只对复合对象有效。用简单的...
  • 最近温习了一下Design Pattern方面的知识,在看到Prototype Pattern这一设计模式时,注意到其中涉及到一个浅复制与深复制的问题。这里来总结一下,提醒自己以后一定要多加注意。 自PHP5起,new运算符自动返回一个...
  • 主要介绍了JavaScript 复制对象与Object.assign方法无法实现深复制,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 本文实例讲述了php5对象复制、clone、浅复制与深复制。分享给大家供大家参考,具体如下: 对象复制的由来 为什么对象会有“复制”这个概念,这与PHP5中对象的传值方式是密切相关的,让我们看看下面这段简单的代码 ...
  • PHP对象的浅复制与深复制的实例详解 ... 实例代码: //聚合类 class ObjA { ... //只有实现了下面方法聚合类 才能实现深复制 /*function __clone() { $this->objB = clone $this->objB; }*/ } class ObjB {
  • 理解python中的深复制和浅复制

    千次阅读 2020-08-10 15:15:45
    深复制和浅复制 在python中一切都是对象,每个对象包含了idendity、type 和 value。所以python中的复制语句实际上是添加引用,将内存地址赋予了一个新的别名。 浅复制 浅复制一般出现在非嵌套的对象当中,python中的...

    深复制和浅复制

    在python中一切都是对象,每个对象包含了idendity、type 和 value。所以python中的复制语句实际上是添加引用,将内存地址赋予了一个新的别名。

    浅复制

    浅复制一般出现在非嵌套的对象当中,python中的非容器对象(num,str,其他原子性对象),元组是个例外,后面会讲,对于复制都使用的是浅复制,不分浅复制和深复制。那么对于容器类对象,像list和dict,浅拷贝和深拷贝就有区分了。下面简单的例子:
    在这里插入图片描述

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    >>> import copy
    >>> b = [1, 2]
    >>> a = [b, 3, 4]
    >>> d = copy.copy(a)
    >>> print(id(d) is id(a))
    False
    >>> print(id(d[0]) is id(a[0]))
    True
    

    上述代码中d创建了一个a的浅复制,这时d会新创建一个对象,所以id(a) neq id(b),但是由于a是一个嵌套的容器对象,那么浅复制就不会复制内层内的b的对象,而是复制b的引用。所以id(d[0]) == id(a[0])。这时修改d[0]中的值同样会改变a[0]中的值。

    浅复制的几种情况:

    • 使用切片[:]操作
    • 使用工厂函数(如list/dir/set)
    • 使用copy模块中的copy()函数

    深复制

    深复制相对应与浅复制,浅复制是只有一层的对象复制,其他层都是引用。而深复制则是递归地进行复制,每一层都是对象复制。因此深复制会复制更多东西,占用更多内存,也比浅复制耗时。以下例子:
    在这里插入图片描述

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    >>> import copy
    >>> b = [1, 2]
    >>> a = [b, 3, 4]
    >>> d = copy.deepcopy(a)
    >>> print(id(d) is id(a))
    False
    >>> print(id(d[0]) is id(a[0]))
    False
    

    d会完全复制a中的所有内容,因此当d和a是两个完全不同的对象,由于递归复制了所有对象,那么显然d[0]和a[0]也是两个不同的对象,两者不相互影响。

    引发的问题

    python二维数组初始化

    如果使用list来初始化一个全0的数组,便很大可能出现问题,对于一维数组,可以简单地使用a = [0] * 3这里就是使用的浅复制。当二维数组时候就会:

    >>> a = [[0] * 3] *3
    >>> a[0][0] = 1
    >>> print(a)
    [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
    

    出现与感觉上相违背的事情,原因是这里的[]*n使用的时浅拷贝,当使用嵌套时,则出现这种错误,上述代码相当于:

    >>> b = [0] * 3
    >>> a = [b, b, b]
    

    正确的初始化方式为生成式[[0 for j in range(3)] for i in range(3)]或者使用nunpy。

    元组修改问题

    元组是不允许修改的,但是如果有以下写法,则是很容易出现问题。例子:

    a = ([1, 2], 3, 4)
    a[0] += [5, 6]
    print(a)
    

    当运行以上程序时,首先会报错:
    TypeError: ‘tuple’ object does not support item assignment,因为元组不允许被修改,但是当打印时会发现:a = ([1, 2, 5, 6], 3, 4),让人觉得很诡异,明明已经报错了,但是元组内的值还是被修改了。这其实因为是+=并不是一个原子操作,先执行的添加,然后再执行的赋值,当赋值时候添加完成了,但是赋值却不被允许。

    展开全文
  • 浅析vue深复制

    2020-08-28 03:13:57
    主要介绍了vue深复制的相关资料,非常不错,具有参考借鉴价值,需要的朋友参考下
  • android 浅复制和深复制-Java Generic Deep Copy 篇
  • 主要帮助大家理解java中的深复制和浅复制,对java中的深复制和浅复制进行剖析,感兴趣的小伙伴们可以参考一下
  • 主要介绍了Java 浅复制和深复制的实例详解的相关资料,这里提供实例帮助大家学习理解这部分内容,需要的朋友可以参考下
  • 主要介绍了 Java对象深复制与浅复制实例详解的相关资料,需要的朋友可以参考下
  • Vue深度复制深度copy

    千次阅读 2019-03-27 12:28:24
    JSON.stringify(value [, replacer] [, space]) 现将引用类型的数据转成字符串类型,然后copy字符串之后转成引用类型
    JSON.stringify(value [, replacer] [, space]) 
    

    现将引用类型的数据转成字符串类型,然后copy字符串之后转成引用类型

    展开全文
  • android 浅复制与深复制

    千次阅读 2017-08-25 09:16:48
    android 浅复制与深复制的内容。 一、前言 任何变成语言中,其实都有浅拷贝和深拷贝的概念,Java 中也不例外。在对一个现有的对象进行拷贝操作的时候,是有浅拷贝和深拷贝之分的,他们在实际使用中,区别很大...


    今天,简单讲讲
    

    android 浅复制与深复制的内容。


    一、前言

    任何变成语言中,其实都有浅拷贝和深拷贝的概念,Java 中也不例外。在对一个现有的对象进行拷贝操作的时候,是有浅拷贝和深拷贝之分的,他们在实际使用中,区别很大,如果对其进行混淆,可能会引发一些难以排查的问题。

    本文就在 Java 中的深拷贝和浅拷贝做一个详细的解说。

    二、什么是浅拷贝和深拷贝

    首先需要明白,浅拷贝和深拷贝都是针对一个已有对象的操作。那先来看看浅拷贝和深拷贝的概念。

    在 Java 中,除了基本数据类型(元类型)之外,还存在 类的实例对象 这个引用数据类型。而一般使用 『 = 』号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。

    而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。

    所以到现在,就应该了解了,所谓的浅拷贝和深拷贝,只是在拷贝对象的时候,对 类的实例对象 这种引用数据类型的不同操作而已。



    三、Java 中的 clone()

    3.1 Object 上的 clone() 方法

    在 Java 中,所有的 Class 都继承自 Object ,而在 Object 上,存在一个 clone() 方法,它被声明为了 protected ,所以我们可以在其子类中,使用它。

    而无论是浅拷贝还是深拷贝,都需要实现 clone() 方法,来完成操作。


    它的实现非常的简单,它限制所有调用 clone() 方法的对象,都必须实现 Cloneable 接口,否者将抛出 CloneNotSupportedException 这个异常。最终会调用 internalClone() 方法来完成具体的操作。而 internalClone() 方法,实则是一个 native 的方法。对此我们就没必要深究了,只需要知道它可以 clone() 一个对象得到一个新的对象实例即可。


    而反观 Cloneable 接口,可以看到它其实什么方法都不需要实现。对他可以简单的理解只是一个标记,是开发者允许这个对象被拷贝。


    具体的使用很简单。

    ⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
    ①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
    ②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
    ③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。

    ⑵Java中对象的克隆

    ①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
    ②在派生类中覆盖基类的clone()方法,并声明为public。
    ③在派生类的clone()方法中,调用super.clone()。
    ④在派生类中实现Cloneable接口。


    请看如下代码:

    public class Student implements Cloneable 
    { 
      String name; 
     int age; 
      Student(String name,int age) 
      { 
      this.name=name; 
      this.age=age; 
      } 
     public Object clone() 
      { 
       Object o=null; 
      try
       { 
       o=(Student)super.clone();//Object 中的clone()识别出你要复制的是哪一个对象。 
       } 
      catch(CloneNotSupportedException e) 
       { 
        System.out.println(e.toString()); 
       } 
      return o; 
      }  
      
     public static void main(String[] args) 
      { 
      Student s1=new Student("zhangsan",18); 
      Student s2=(Student)s1.clone(); 
      s2.name="lisi"; 
      s2.age=20; 
      //修改学生2后,不影响学生1的值。
      System.out.println("name="+s1.name+","+"age="+s1.age); 
      System.out.println("name="+s2.name+","+"age="+s2.age);
     }
    }
    


    说明:
    ①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。


    ②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。

    class Professor 
    { 
      String name; 
      int age; 
      Professor(String name,int age) 
      { 
      this.name=name; 
      this.age=age; 
      } 
    } 
    public class Student implements Cloneable 
    { 
      String name;// 常量对象。 
      int age; 
      Professor p;// 学生1和学生2的引用值都是一样的。 
      Student(String name,int age,Professor p) 
      { 
      this.name=name; 
      this.age=age; 
      this.p=p; 
      } 
     public Object clone() 
      { 
       Student o=null; 
      try
       { 
        o=(Student)super.clone(); 
       } 
      catch(CloneNotSupportedException e) 
       { 
        System.out.println(e.toString()); 
       } 
       o.p=(Professor)p.clone(); 
      return o; 
      }  
     public static void main(String[] args) 
     { 
      Professor p=new Professor("wangwu",50); 
      Student s1=new Student("zhangsan",18,p); 
      Student s2=(Student)s1.clone(); 
      s2.p.name="lisi"; 
      s2.p.age=30;  
      System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
      System.out.println("name="+s2.p.name+","+"age="+s2.p.age);
      //输出结果学生1和2的教授成为lisi,age为30。
      } 
    }
    


    那应该如何实现深层次的克隆,即修改s2的教授不会影响s1的教授?代码改进如下。
    改进使学生1的Professor不改变(深层次的克隆)

    class Professor implements Cloneable 
    { 
      String name; 
      int age; 
      Professor(String name,int age) 
      { 
      this.name=name; 
      this.age=age; 
      } 
     public Object clone() 
      { 
       Object o=null; 
      try
       { 
        o=super.clone(); 
       } 
      catch(CloneNotSupportedException e) 
       { 
        System.out.println(e.toString()); 
       } 
      return o; 
      } 
    } 
    public class Student implements Cloneable 
    { 
      String name; 
      int age; 
      Professor p; 
      Student(String name,int age,Professor p) 
      { 
      this.name=name; 
      this.age=age; 
      this.p=p; 
      } 
     public Object clone() 
      { 
       Student o=null; 
      try
       { 
        o=(Student)super.clone(); 
       } 
      catch(CloneNotSupportedException e) 
       { 
        System.out.println(e.toString()); 
       } 
       //对引用的对象也进行复制
       o.p=(Professor)p.clone(); 
      return o; 
      }  
     public static void main(String[] args) 
      { 
      Professor p=new Professor("wangwu",50); 
      Student s1=new Student("zhangsan",18,p); 
      Student s2=(Student)s1.clone(); 
      s2.p.name="lisi"; 
      s2.p.age=30; 
      //学生1的教授不 改变。
      System.out.println("name="+s1.p.name+","+"age="+s1.p.age); 
      System.out.println("name="+s2.p.name+","+"age="+s2.p.age); 
     } 
    }
    



    3.利用串行化来做深复制(主要是为了避免重写比较复杂对象的深复制的clone()方法,也可以程序实现断点续传等等功能)
        把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做 “解冻”或者“回鲜(depicking)”过程。
        应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
        在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
    如下为深复制源代码。

    public Object deepClone() 
    { 
     //将对象写到流里 
     ByteArrayOutoutStream bo=new ByteArrayOutputStream(); 
     ObjectOutputStream oo=new ObjectOutputStream(bo); 
     oo.writeObject(this); 
     //从流里读出来 
     ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray()); 
     ObjectInputStream oi=new ObjectInputStream(bi); 
     return(oi.readObject()); 
    }
    


    这样做的前提是对象以及对象内部所有引用到的对象都是可串行化的,否则,就需要仔细考察那些不可串行化的对象或属性可否设成transient,从而将之排除在复制过程之外。上例代码改进如下。

    class Teacher implements Serializable{
      String name;
      int age;
      public void Teacher(String name,int age){
      this.name=name;
      this.age=age;
      }
    }
    public class Student implements Serializable{
     String name;//常量对象
     int age;
     Teacher t;//学生1和学生2的引用值都是一样的。
     public void Student(String name,int age,Teacher t){
      this.name=name;
      this.age=age;
      this.p=p;
     }
     public Object deepClone() throws IOException,
        OptionalDataException,ClassNotFoundException{//将对象写到流里
      ByteArrayOutoutStream bo=new ByteArrayOutputStream();
      ObjectOutputStream oo=new ObjectOutputStream(bo);
      oo.writeObject(this);//从流里读出来
      ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
      ObjectInputStream oi=new ObjectInputStream(bi);
      return(oi.readObject());
     }
     public static void main(String[] args){ 
      Teacher t=new Teacher("tangliang",30);
      Student s1=new Student("zhangsan",18,t);
      Student s2=(Student)s1.deepClone();
      s2.t.name="tony";
      s2.t.age=40;
      //学生1的老师不改变
      System.out.println("name="+s1.t.name+","+"age="+s1.t.age);
     }
    }
    



    总之,可以通过重写clone来实现对象的复制,也可以通过序列号实现对象的复制。


    android 浅复制与深复制就讲完了。


    就这么简单。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 267,736
精华内容 107,094
关键字:

深复制