Java中的深拷贝与浅拷贝

举报
兴趣使然的草帽路飞 发表于 2021/06/09 00:53:13 2021/06/09
【摘要】 深拷贝和浅拷贝区别是什么? 数据分为基本数据类型和引用数据类型。基本数据类型:数据直接存储在栈中;引用数据类型:存储在栈中的是对象的引用地址,真实的对象数据存放在堆内存里。浅拷贝:对于基础数据类型:直接复制数据值;对于引用数据类型:只是复制了对象的引用地址,新旧对象指向同一个内存地址,修改其中一个对象的值,另一个对象的值随之改变。深拷贝:对于基础数据类型:直...

深拷贝和浅拷贝区别是什么?

  • 数据分为基本数据类型和引用数据类型。基本数据类型:数据直接存储在栈中;引用数据类型:存储在栈中的是对象的引用地址,真实的对象数据存放在堆内存里。
  • 浅拷贝:对于基础数据类型:直接复制数据值;对于引用数据类型:只是复制了对象的引用地址,新旧对象指向同一个内存地址,修改其中一个对象的值,另一个对象的值随之改变。
  • 深拷贝:对于基础数据类型:直接复制数据值;对于引用数据类型:开辟新的内存空间,在新的内存空间里复制一个一模一样的对象,新老对象不共享内存,修改其中一个对象的值,不会影响另一个对象。
  • 深拷贝相比于浅拷贝速度较慢并且花销较大。

深拷贝/浅拷贝分析案例

  • 浅拷贝实现 Cloneable,深拷贝是通过实现 Serializable 读取二进制流

深拷贝实现

首先Person 对象实现 Serializable 接口,然后自定义深拷贝方法 deepClone()

/**
 * 深拷贝
 * 
 * 注意:要实现序列化接口
 * @return
 */
public Person deepClone() { try { // 输出 (序列化) ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(this); // 输入 (反序列化) ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); Person person = (Person) ois.readObject(); return person; } catch (Exception e) { e.printStackTrace(); return null; }
}

  
 

接下来验证一下深拷贝是否成功:

@Test
public void testPropotype() throws CloneNotSupportedException { Person person1 = new Person(); person1.setAge(22); person1.setName("csp"); // 初始化list 并为其加入数据 person1.setList(new ArrayList<>()); person1.getList().add("aaa"); person1.getList().add("bbb"); System.out.println("person1:"+person1); //-----------------------------浅拷贝------------------------------- //Person person2 = person1.clone(); //-----------------------------深拷贝------------------------------- Person person2 = person1.deepClone(); person2.setName("hzw"); // 给peron2 中的list添加一条数据 person2.getList().add("ccc"); System.out.println("person2"+person2); System.out.println("person1:"+person1); boolean flag1 = person1 == person2; System.out.println("person1 和 person2 的 引用地址是否相同: " +  flag1); boolean flag2 = person1.getList() == person2.getList(); System.out.println("person1 和 person2 的 list 引用地址是否相同: " +  flag2);
}

  
 

输出结果:

空参构造函数调用...
person1:Person{name='csp', age=22, list=[aaa, bbb]}
person2Person{name='hzw', age=22, list=[aaa, bbb, ccc]}
person1:Person{name='csp', age=22, list=[aaa, bbb]}
person1 和 person2 的 引用地址是否相同: false
person1 和 person2 的 list 引用地址是否相同: false

  
 

由结果可得出:深拷贝 person2 所得到的 list 内存地址和原来person1 中的内存地址是不同的,深拷贝成功!

文章来源: csp1999.blog.csdn.net,作者:兴趣使然の草帽路飞,版权归原作者所有,如需转载,请联系作者。

原文链接:csp1999.blog.csdn.net/article/details/115702607

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。