前言

对象拷贝Object Copy是将一个对象的属性,拷贝到另一个相同类型的对象中。拷贝对象主要是为了在新的上下文环境中复用对象的部分或全部数据。其中对象拷贝有3种类型:深拷贝Deep Copy、浅拷贝Shallow Copy和延迟拷贝Lazy Copy。

浅拷贝

按位拷贝对象,它会创建一个新的对象,该对象有这原始对象属性值的备份。如果属性是基本类型,拷贝的就是基本类型的值。如果属性是内存地址(引用类型),拷贝的就是内存地址。所以,如果其中一个对象改变了这个地址,另一个对象也得“受牵连”。
SourceObject有一个int类型的属性field1、一个引用属性refObj。当SourceObject做浅拷贝时,创建了CopiedObject。CopiedObject包含一个field1拷贝值的属性field2、指向refObj的引用。基本类型直接拷贝,引用类型指向相同地址。对SourceObject中的refObj做修改,CopiedObject也会改变。

实现浅拷贝

public class Subject {private String name;public Subject(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
public class Student implements Cloneable {//对象引用private Subject subj;private String name;public Student(String s, String sub) {this.subj = new Subject(sub);this.name = s;}public Subject getSubj() {return subj;}public void setSubj(Subject subj) {this.subj = subj;}public String getName() {return name;}public void setName(String name) {this.name = name;}//重写clone方法public Object clone(){//浅拷贝try {//直接调用父类clone方法return super.clone();}catch (CloneNotSupportedException e){return null;}}
}
public class CopyTest {public static void main(String []args){//原始对象Student student = new Student("husky", "labrador");System.out.println(student.getName()+"---"+student.getSubj().getName());//拷贝对象Student cloneStudent = (Student) student.clone();System.out.println(cloneStudent.getName()+"---"+cloneStudent.getSubj().getName());//原始对象和拷贝对象是否一样System.out.println("两者是否一样:"+(student==cloneStudent));//原始对象和拷贝对象的name属性是否一致?System.out.println("name是否一致:"+(student.getName()==cloneStudent.getName()));//原始对象和拷贝对象的subj是否一致?System.out.println("subj属性:"+(student.getSubj()==cloneStudent.getSubj()));student.setName("大G");student.getSubj().setName("狂风桑");System.out.println("修改后的name:"+student.getName()+"<>"+student.getSubj().getName());System.out.println("修改后的subj"+cloneStudent.getName()+"<>"+cloneStudent.getSubj().getName());}
}

输出结果:

husky---labrador
husky---labrador
两者是否一样:false
name是否一致:true
subj属性:true
修改后的name:大G<>狂风桑
修改后的subjhusky<>狂风桑

使拷贝的Student类实现Clonable接口并重写clone方法,方法内调用super.clone()。从输出结果看到,对原始对象的name改变并不影响拷贝对象。但是引用对象subj的name改变,拷贝对象的也被牵连。

深拷贝

深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它引用的对象一起拷贝时就会发生深拷贝。深拷贝较浅拷贝而言,速度慢花销大。
SourceObject有一个int类型的field1属性和一个引用类型属性refObj1,当做深拷贝时,创建了CopiedObject,包含一个field1拷贝值的属性field2和refObj1拷贝值的引用类型属性refObj2。对SourceObject中的refObj做的改变,不会影响到CopiedObject

实现深拷贝

public class Subject {private String name;public Subject(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
public class Student implements Cloneable {//对象引用private Subject subj;private String name;public Student(String s, String sub) {this.subj = new Subject(sub);this.name = s;}public Subject getSubj() {return subj;}public void setSubj(Subject subj) {this.subj = subj;}public String getName() {return name;}public void setName(String name) {this.name = name;}//重写clone方法public Object clone(){//浅拷贝Student student = new Student(name, subj.getName());return student;}
}
public class CopyTest {public static void main(String []args){//原始对象Student student = new Student("husky", "labrador");System.out.println(student.getName()+"---"+student.getSubj().getName());//拷贝对象Student cloneStudent = (Student) student.clone();System.out.println(cloneStudent.getName()+"---"+cloneStudent.getSubj().getName());//原始对象和拷贝对象是否一样System.out.println("两者是否一样:"+(student==cloneStudent));//原始对象和拷贝对象的name属性是否一致?System.out.println("name是否一致:"+(student.getName()==cloneStudent.getName()));//原始对象和拷贝对象的subj是否一致?System.out.println("subj属性:"+(student.getSubj()==cloneStudent.getSubj()));student.setName("大G");student.getSubj().setName("狂风桑");System.out.println("修改后的name:"+student.getName()+"<>"+student.getSubj().getName());System.out.println("修改后的subj:"+cloneStudent.getName()+"<>"+cloneStudent.getSubj().getName());}
}

输出结果:

husky---labrador
husky---labrador
两者是否一样:false
name是否一致:true
subj属性:false
修改后的name:大G<>狂风桑
修改后的subj:husky<>labrador

通过序列化实现深拷贝

序列化就是将整个对象图写入到一个持久化存储文件中,并在需要的时候读取回来。读取回来时,意味着我需要整个对象图的一个拷贝。而且,通过序列化做深拷贝时,需要确定整个对象图中的所有类都是可序列化的。

public class ColoredCircle implements Serializable {private int x;private int y;public ColoredCircle(int x, int y) {this.x = x;this.y = y;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}@Overridepublic String toString() {return "x:"+x+";y:"+y;}
}
public class DeepCopy {public static void main(String []args) throws IOException{ObjectOutputStream oos = null;ObjectInputStream ois = null;try {//创建原始的可序列化对象ColoredCircle c1 = new ColoredCircle(100, 100);System.out.println("原始可序列化对象c1:"+c1);ColoredCircle c2 = null;//通过序列化实现深拷贝ByteArrayOutputStream bos = new ByteArrayOutputStream();oos = new ObjectOutputStream(bos);//序列化及传递这个对象oos.writeObject(c1);oos.flush();ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());ois = new ObjectInputStream(bin);//返回新的对象c2 = (ColoredCircle)ois.readObject();//检验内容是否相同System.out.println("copy:"+c2);//改变原始对象内容c1.setX(200);c1.setY(200);//查看每一个现在的内容System.out.println("现在的c1:"+c1);System.out.println("现在的c2:"+c2);}catch (Exception e){System.out.println("异常:"+e);}finally {oos.close();ois.close();}}
}

输出结果:

原始可序列化对象c1:x:100;y:100
copy:x:100;y:100
现在的c1:x:200;y:200
现在的c2:x:100;y:100

这里要先确认:
1.对象图中所有的类都是可序列化的
2.创建输入、输出流
3.使用这个输入、输出流来创建对象输入流、对象输出流
4.将要拷贝的对象传递给对象输出流
5.从对象输入流中读取新的对象,并转换回你所发送的对象的类
问题:
1.无法序列化transient变量
2.创建一个socket,序列化一个对象,通过socket传输,反序列化,过程很慢。

延迟拷贝

延迟拷贝是深拷贝与浅拷贝的组合,先使用速度快的浅拷贝,使用一个计数器来记录有多少对象来共享这个数据。当程序想要修改原始对象时,它会通过检查计数器决定数据是否被共享,并根据需要进行深拷贝。

Java深拷贝与浅拷贝相关推荐

  1. 面试官:Java深拷贝和浅拷贝区别

    文章目录 一.拷贝的引入 (1).引用拷贝 (2).对象拷贝 二.浅拷贝 (1).定义 (2).浅拷贝实例 三.深拷贝 (1).定义 (2).深拷贝实例 一.拷贝的引入 (1).引用拷贝 创建一个指向 ...

  2. java -- 深拷贝和浅拷贝的区别 如何实现深拷贝和浅拷贝

    文章目录 1. 深拷贝和浅拷贝的区别 1.1 浅拷贝实例 1.1.1 测试1 直接赋值 1.1.2 测试2 改变源对象的值 1.2 深拷贝实例 `这是用于深拷贝的测试类` 1.2.1 方法一: 构造函 ...

  3. java 深拷贝和浅拷贝

    深拷贝和浅拷贝的问题无非就是拷贝过程中对象的属性是否指向的是同一个对象引用. 浅拷贝的特点: 一:作为基本数据类型来说,例如int ,double等8类数据类型,拷贝过程中肯定是值的传递,修改另一个对 ...

  4. 浅谈对java深拷贝与浅拷贝的理解

    java中什么是浅拷贝?什么是深拷贝? 1.拷贝:实现对象复制的方式. 2.浅拷贝:被复制的对象的所有变量都含有原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之, 浅拷贝仅仅复制所 ...

  5. java深拷贝和浅拷贝_Java 深拷贝浅拷贝 与 序列化

    一.浅拷贝.深拷贝 浅拷贝会对对象中的成员变量进行拷贝:如果是基本类型,拷贝的就是基本类型的值:如果属性是内存地址(引用类型),拷贝的就是内存地址 : 深拷贝,除了基本类型外,引用类型所引用的对象也会 ...

  6. java深拷贝和浅拷贝介绍

    浅拷贝概念 深拷贝概念 @Data @Slf4j public class Sheep implements Cloneable {private String name;private int ag ...

  7. java 深拷贝_java 深拷贝与浅拷贝机制详解

    java 深拷贝与浅拷贝机制详解 概要: 在Java中,拷贝分为深拷贝和浅拷贝两种.java在公共超类Object中实现了一种叫做clone的方法,这种方法clone出来的新对象为浅拷贝,而通过自己定 ...

  8. java拷贝函数_Java的深拷贝与浅拷贝的几种实现方式

    1.介绍 关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象.可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传 ...

  9. Java 深入理解深拷贝和浅拷贝区别

    title: Java 深入理解深拷贝和浅拷贝区别 date: 2021-6-19 updated: 2021-6-19 tags: Java 深拷贝和浅拷贝 categories: 面试 Java ...

最新文章

  1. 树莓派 之 Screen
  2. java导入lucene_如何导入lucene的.jar包 ?
  3. selenium自动化之鼠标操作
  4. Java 线程数据交换控制器Exchange使用实例
  5. Ubuntu一键安装LAMP环境
  6. 你会因为贫富差距远离曾经的好友吗?
  7. Win11系统如何隐藏快速搜索
  8. SpringCloud学习笔记013---Spring的@PostConstruct标签_初始化项目字典
  9. C# 3.0新语言特性和改进
  10. c# 循环给数组每个元素加个逗号_C#规范整理集合和Linq
  11. 删除本地oracle数据库,如何在WINDOWS 2000将ORALCE完全卸载-数据库专栏,ORACLE
  12. Spring框架学习---Spring Framework下篇
  13. 知了课堂Day1——微信小程序基础01-template、事件
  14. 判断两个单词是否互为变位词,如“book”,“koob”,代码如下
  15. 【论文阅读】Deep Learning for Encrypted Traffic Classification: An Overview(深度学习方法进行加密流量分类综述)
  16. 一万块的iPhone X来了,你看好苹果的黑科技吗?
  17. 电气绘图软件EPLAN在WIN10详细安装教程
  18. 微信跳一跳python自动代码解读1.0
  19. Android 底层知识拾零,android原生开发框架
  20. WIN7访问局域网内另外一台电脑的共享文件夹

热门文章

  1. 图像处理 区域删除_FotoWorks XL( 图像处理软件 )中文版分享
  2. class不生效 weblogic_weblogic下更改jsp不生效的解决办法
  3. c++ 包络谱分析代码_基于特征分析谱估计算法(Capon, MUSIC, ESPRIT)的C++实现
  4. 半监督学习下的高维图构建
  5. 安全攻防之SQL注入
  6. 禁止显示“You have new mail in /var/spool/mail/root”
  7. Mozilla停止对Firefox Hello的支持(采访)
  8. Apache的Rewrite规则详细介绍
  9. 微软职位内部推荐-Software Engineer II-Data Mini
  10. OCCI入门(VC2010下配置)