ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java浅拷贝深拷贝

2022-08-16 11:00:30  阅读:231  来源: 互联网

标签:Java name clone Person person1 拷贝 age



Java浅拷贝深拷贝

浅拷贝和深拷贝涉及到了Object类中的clone()方法

 

 

实现浅拷贝

浅拷贝的实现需要类重写clone()方法

浅拷贝会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝

  • 如果属性是基本类型,拷贝的就是基本类型的值;

  • 如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象,导致两个对象的引用不等。

实现浅拷贝很简单只需要将类实现Cloneable接口然后重写clone方法即可

 class Person implements Cloneable {
     String name;
     int age;
 ​
     public Person() {
    }
 ​
     public Person(String name, int age) {
         this.name = name;
         this.age = age;
    }
 ​
     public String getName() {
         return name;
    }
 ​
     public void setName(String name) {
         this.name = name;
    }
 ​
     public int getAge() {
         return age;
    }
 ​
     public void setAge(int age) {
         this.age = age;
    }
 ​
     /**
          * 重写clone()方法
          *
          * @return
          * @throws CloneNotSupportedException
          */
     @Override
     protected Object clone() throws CloneNotSupportedException {
         return super.clone();
    }
 ​
     @Override
     public String toString() {
         return "Person{" +
             "name='" + name + '\'' +
             ", age=" + age +
             '}';
    }
 }

测试浅拷贝特性

 public void testClone() throws CloneNotSupportedException {
     Person person1 = new Person();
     person1.setName("ccy");
     person1.setAge(20);
     Person person2 = (Person) person1.clone();
     //查看浅拷贝效果
     System.out.println(person1);
     System.out.println(person2);
     System.out.println(person1.getName() == person2.getName());
     //验证clone()的特性
     System.out.println(person1.clone() != person1);
     System.out.println(person1.clone().getClass() == person1.getClass());
     //如果是基本类型浅拷贝直接赋值值,如果是引用类型浅拷贝指向其内存地址即共享内存地址
     //改变person1的引用类型String属性的值,引用发生改变
     person1.setName("zfs");
     System.out.println(person2.getName());
 }

 

 

实现深拷贝

对于上述的问题虽然拷贝的两个对象不同,但其内部的一些引用还是相同的,怎么样绝对的拷贝这个对象,使这个对象完全独立于原对象呢?就使用我们的深拷贝了。深拷贝:在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量。

在具体实现深拷贝上,这里提供两个方式,重写clone()方法和序列法。

重写clone()方法

如果使用重写clone()方法实现深拷贝,那么要将类中所有自定义引用变量的类也去实现Cloneable接口实现clone()方法。对于字符类可以创建一个新的字符串实现拷贝。但是对于自定义类需要实现cloneable重写clone,这样做就太麻烦了所以我们使用序列化

序列化

序列化后将二进制字节流内容写到一个媒介(文本或字节数组),然后是从这个媒介读取数据,原对象写入这个媒介后拷贝给clone对象,原对象的修改不会影响clone对象,因为clone对象是从这个媒介读取。

熟悉对象缓存的知道我们经常将Java对象缓存到Redis中,然后还可能从Redis中读取生成Java对象,这就用到序列化和反序列化。一般可以将Java对象存储为字节流或者json串然后反序列化成Java对象。因为序列化会储存对象的属性但是不会也无法存储对象在内存中地址相关信息。所以在反序列化成Java对象时候会重新创建所有的引用对象。

在具体实现上,自定义的类需要实现Serializable接口

 class Person implements Serializable {
     String name;
     int age;
 ​
     public Person() {
    }
 ​
     public Person(String name, int age) {
         this.name = name;
         this.age = age;
    }
 ​
     public String getName() {
         return name;
    }
 ​
     public void setName(String name) {
         this.name = name;
    }
 ​
     public int getAge() {
         return age;
    }
 ​
     public void setAge(int age) {
         this.age = age;
    }
 ​
     @Override
     public String toString() {
         return "Person{" +
             "name='" + name + '\'' +
             ", age=" + age +
             '}';
    }
 ​
     protected Person deepClone() throws Exception {
         //序列化
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(bos);
 ​
         oos.writeObject(this);
 ​
         //反序列化
         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
         ObjectInputStream ois = new ObjectInputStream(bis);
 ​
         return (Person) ois.readObject();
    }
 }

测试方法

 public void testClone() throws Exception {
     Person person1 = new Person();
     person1.setName("ccy");
     person1.setAge(20);
     Person person2 = person1.deepClone();
     System.out.println(person1.getName() == person2.getName());
 }

 

 

可以看到两个引用对象的地址并不同,成功实现了深拷贝

标签:Java,name,clone,Person,person1,拷贝,age
来源: https://www.cnblogs.com/ccywmbc/p/16590857.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有