• 2种方法实现java对象的深拷贝


    2种方法实现java对象的深拷贝

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/caoxiaohong1005/article/details/78704890

    1、如果一个类没有实现Cloneable接口,直接调用clone()方法,会报异常CloneNotSupportedException,这一点已经在Object源码中写道:

    1.  
      * @return a clone of this instance.
    2.  
      * @exception CloneNotSupportedException if the object's class does not
    3.  
      * support the {@code Cloneable} interface. Subclasses
    4.  
      * that override the {@code clone} method can also
    5.  
      * throw this exception to indicate that an instance cannot
    6.  
      * be cloned.
    7.  
      * @see java.lang.Cloneable
    8.  
      */
    9.  
      protected native Object clone() throws CloneNotSupportedException;

    
    
    
    
    
    

    而且,源码也写到Object的clone()方法是浅拷贝的,这一点在之前的Object源码分析中我已经写过了.

    
    

    2、自定义类实现深拷贝方法有2种,下面依次给出具体写法。

    2.1、自定义类要实现Cloneable接口,并覆写clone()方法。

    1.  
      /**
    2.  
      * 深拷贝和浅拷贝的测试
    3.  
      */
    4.  
      //测试类1
    5.  
      class Person implements Cloneable{
    6.  
      String name;
    7.  
      int age;
    8.  
      Person(String name,int age){
    9.  
      this.name=name;
    10.  
      this.age=age;
    11.  
      }
    12.  
      @Override
    13.  
      public Object clone() {
    14.  
      try{
    15.  
      return super.clone();
    16.  
      }catch(CloneNotSupportedException e){
    17.  
      return null;
    18.  
      }
    19.  
      }
    20.  
      }
    21.  
      //测试类2
    22.  
       
    23.  
      class Animal implements Cloneable{
    24.  
      Person host;//主人
    25.  
      int age;//年纪
    26.  
      Animal(Person person,int age){
    27.  
      this.host=person;
    28.  
      this.age=age;
    29.  
      }
    30.  
      @Override
    31.  
      public Object clone(){
    32.  
      try{
    33.  
      Animal animal=(Animal) super.clone();
    34.  
      animal.host=(Person)host.clone();//深拷贝处理
    35.  
      return animal;
    36.  
      }catch (CloneNotSupportedException e){
    37.  
      return null;
    38.  
      }
    39.  
      }
    40.  
      }
    41.  
       
    42.  
      //测试
    43.  
      public class Main{
    44.  
      public static void main(String[] args) {
    45.  
      Person person1=new Person("cxh",26);
    46.  
      Person person2=(Person)person1.clone();
    47.  
      System.out.println("----------------浅拷贝--------------");
    48.  
      //测试Object的clone方法为浅拷贝
    49.  
      //String类用==测试内存地址是否一致
    50.  
      System.out.println("person1和person2的name内存地址是否相同:"+(person1.name==person2.name));
    51.  
       
    52.  
       
    53.  
       
    54.  
      System.out.println("----------------深拷贝--------------");
    55.  
      //重写Object的clone方法,实现深拷贝
    56.  
      //还是用==查看两个对象的内存地址是否相等来确定是否为两个对象,如果是两个内存地址,那么就是深拷贝
    57.  
      Animal animal1=new Animal(new Person("cxh",26),3);
    58.  
      Animal animal2=(Animal) animal1.clone();
    59.  
      System.out.println("animal1和animal2的host内存地址是否相同:"+(animal1.host==animal2.host));
    60.  
      }
    61.  
      }

    输出:
    
    
    
    
    
    1.  
      ----------------浅拷贝--------------
    2.  
      person1和person2的name内存地址是否相同:true
    3.  
      ----------------深拷贝--------------
    4.  
      animal1和animal2的host内存地址是否相同:false
    5.  
       
    6.  
      Process finished with exit code 0

    一个讲解很详细的博客:http://blog.csdn.net/zhangjg_blog/article/details/18369201


    
    
    

    2.2、通过序列化方式实现深拷贝:先将要拷贝对象写入到内存中的字节流中,然后再从这个字节流中读出刚刚存储的信息,作为一个新对象返回,那么这个新对象和原对象就不存在任何地址上的共享,自然实现了深拷贝。

    自定义类需要实现Serializable接口。

    1.  
      import java.io.*;
    2.  
       
    3.  
      /**
    4.  
      * 深拷贝和浅拷贝的测试
    5.  
      * 如何利用序列化来完成对象的拷贝呢?在内存中通过字节流的拷贝是比较容易实现的。把母对象写入到一个字节流中,再从字节流中将其读出来,
    6.  
      * 这样就可以创建一个新的对象了,并且该新对象与母对象之间并不存在引用共享的问题,真正实现对象的深拷贝。
    7.  
      */
    8.  
      //工具类
    9.  
      class CloneUtil{
    10.  
      public static <T extends Serializable> T clone(T obj){
    11.  
      T cloneObj=null;
    12.  
      try{
    13.  
      //写入字节流
    14.  
      ByteArrayOutputStream baos=new ByteArrayOutputStream();
    15.  
      ObjectOutputStream oos=new ObjectOutputStream(baos);
    16.  
      oos.writeObject(obj);
    17.  
      oos.close();
    18.  
       
    19.  
      //分配内存,写入原始对象,生成新对象
    20.  
      ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());//获取上面的输出字节流
    21.  
      ObjectInputStream ois=new ObjectInputStream(bais);
    22.  
       
    23.  
      //返回生成的新对象
    24.  
      cloneObj=(T)ois.readObject();
    25.  
      ois.close();
    26.  
      }catch (Exception e){
    27.  
      e.printStackTrace();
    28.  
      }
    29.  
      return cloneObj;
    30.  
      }
    31.  
      }
    32.  
       
    33.  
      //测试类1
    34.  
      class Person implements Serializable{
    35.  
      String name;
    36.  
      int age;
    37.  
      Person(String name,int age){
    38.  
      this.name=name;
    39.  
      this.age=age;
    40.  
      }
    41.  
       
    42.  
      }
    43.  
      //测试类2
    44.  
       
    45.  
      class Animal implements Serializable{
    46.  
      Person host;//主人
    47.  
      int age;//年纪
    48.  
      Animal(Person person,int age){
    49.  
      this.host=person;
    50.  
      this.age=age;
    51.  
      }
    52.  
      }
    53.  
       
    54.  
       
    55.  
      //测试
    56.  
      public class Main{
    57.  
      public static void main(String[] args) {
    58.  
      System.out.println("----------------深拷贝--------------");
    59.  
      //重写Object的clone方法,实现深拷贝
    60.  
      //还是用==查看两个对象的内存地址是否相等来确定是否为两个对象,如果是两个内存地址,那么就是深拷贝
    61.  
      Animal animal1=new Animal(new Person("cxh",26),3);
    62.  
      Animal animal2=CloneUtil.clone(animal1);
    63.  
      System.out.println("animal1和animal2的host内存地址是否相同:"+(animal1.host==animal2.host));
    64.  
      }
    65.  
      }

    输出结果:
    1.  
      ----------------深拷贝--------------
    2.  
      animal1和animal2的host内存地址是否相同:false

    参考博客:http://blog.csdn.net/chenssy/article/details/12952063
  • 相关阅读:
    某些电脑前面板没声音问题
    安装win10笔记
    linux 时区问题
    JS实现网页飘窗
    缓存promise技术不错哦
    wepy相关
    生成keystore
    2017年终巨献阿里、腾讯最新Java程序员面试题,准备好进BAT了吗
    细思极恐-你真的会写java吗
    年终盘点:Java今年的大事记都在这里!
  • 原文地址:https://www.cnblogs.com/think90/p/11440153.html
Copyright © 2020-2023  润新知