博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2种方法实现java对象的深拷贝
阅读量:5288 次
发布时间:2019-06-14

本文共 3720 字,大约阅读时间需要 12 分钟。

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

版权声明:本文为博主原创文章,遵循版权协议,转载请附上原文出处链接和本声明。
本文链接:

 

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

 

一个讲解很详细的博客:

 

 

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
参考博客:

转载于:https://www.cnblogs.com/think90/p/11440153.html

你可能感兴趣的文章
【java项目实战】代理模式(Proxy Pattern),静态代理 VS 动态代理
查看>>
springboot项目中配置swagger-ui
查看>>
forward和redirect的区别详解
查看>>
inno setup介绍及官方网站地址
查看>>
一个简单的拼写检查器
查看>>
win10更换登陆背景和关闭锁屏
查看>>
20175126《Java程序设计》第七周学习总结
查看>>
导出文件名乱码解决方案
查看>>
Leetcode Convert Sorted Array to Binary Search Tree
查看>>
CentOS6和CentOS7安装jumpserver
查看>>
hdu 1276士兵队列问题【queue】
查看>>
nandflash裸机程序分析
查看>>
Bzoj 2038: [2009国家集训队]小Z的袜子(hose)
查看>>
图片字节流生成bmp文件
查看>>
常用函数、文本处理函数、日期函数
查看>>
.net core下获取自身服务器地址
查看>>
Solr 07 - Solr从MySQL数据库中导入数据 (Solr DIH的使用示例)
查看>>
netty常用代码
查看>>
201671010140. 2016-2017-2 《Java程序设计》java学习第十六周
查看>>
字符编码
查看>>