JAVA 深复制与浅复制
来源:互联网 发布:linux yum安装maven 编辑:程序博客网 时间:2024/06/03 17:10
一、引言
对象拷贝(Object Copy)就是将一个对象的属性拷贝到另一个有着相同类类型的对象中去。在程序中拷贝对象是很常见的,主要是为了在新的上下文环境中复用对象的部分或全部 数据。Java中有三种类型的对象拷贝:浅拷贝(Shallow Copy)、深拷贝(Deep Copy)、延迟拷贝(Lazy Copy)。
二、浅拷贝
1、什么是浅拷贝
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
在图中,SourceObject有一个int类型的属性 "field1"和一个引用类型属性"refObj"(引用ContainedObject类型的对象)。当对SourceObject做浅拷贝时,创建了CopiedObject,它有一个包含"field1"拷贝值的属性"field2"以及仍指向refObj本身的引用。由于"field1"是基本类型,所以只是将它的值拷贝给"field2",但是由于"refObj"是一个引用类型, 所以CopiedObject指向"refObj"相同的地址。因此对SourceObject中的"refObj"所做的任何改变都会影响到CopiedObject。
2、用例:
public class Subject { private String name; public Subject(String s) { name = s; } public String getName() { return name; } public void setName(String s) { name = s; } }public class Student implements Cloneable { // 对象引用 private Subject subj; private String name; public Student(String s, String sub) { name = s; subj = new Subject(sub); } public Subject getSubj() { return subj; } public String getName() { return name; } public void setName(String s) { name = s; } /** * 重写clone()方法 * @return */ public Object clone() { //浅拷贝 try { // 直接调用父类的clone()方法 return super.clone(); } catch (CloneNotSupportedException e) { return null; } } }public class CopyTest { public static void main(String[] args) { // 原始对象 Student stud = new Student("John", "Algebra"); System.out.println("Original Object: " + stud.getName() + " - " + stud.getSubj().getName()); // 拷贝对象 Student clonedStud = (Student) stud.clone(); System.out.println("Cloned Object: " + clonedStud.getName() + " - " + clonedStud.getSubj().getName()); // 原始对象和拷贝对象是否一样: System.out.println("Is Original Object the same with Cloned Object: " + (stud == clonedStud)); // 原始对象和拷贝对象的name属性是否一样 System.out.println("Is Original Object's field name the same with Cloned Object: " + (stud.getName() == clonedStud.getName())); // 原始对象和拷贝对象的subj属性是否一样 System.out.println("Is Original Object's field subj the same with Cloned Object: " + (stud.getSubj() == clonedStud.getSubj())); stud.setName("Dan"); stud.getSubj().setName("Physics"); System.out.println("Original Object after it is updated: " + stud.getName() + " - " + stud.getSubj().getName()); System.out.println("Cloned Object after updating original object: " + clonedStud.getName() + " - " + clonedStud.getSubj().getName()); }}结果:
Original Object: John - Algebra Cloned Object: John - Algebra Is Original Object the same with Cloned Object: false Is Original Object's field name the same with Cloned Object: true Is Original Object's field subj the same with Cloned Object: true Original Object after it is updated: Dan - Physics Cloned Object after updating original object: John - Physics
三、深拷贝
1、什么是深拷贝
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
在上图中,SourceObject有一个int类型的属性 "field1"和一个引用类型属性"refObj1"(引用ContainedObject类型的对象)。当对SourceObject做深拷贝时,创建了CopiedObject,它有一个包含"field1"拷贝值的属性"field2"以及包含"refObj1"拷贝值的引用类型属性"refObj2" 。因此对SourceObject中的"refObj"所做的任何改变都不会影响到CopiedObject
2、用例:(在浅复制的基础上修改)
public class Student implements Cloneable { // 对象引用 private Subject subj; private String name; public Student(String s, String sub) { name = s; subj = new Subject(sub); } public Subject getSubj() { return subj; } public String getName() { return name; } public void setName(String s) { name = s; } /** * 重写clone()方法 * * @return */ public Object clone() { // 深拷贝,创建拷贝类的一个新对象,这样就和原始对象相互独立 Student s = new Student(name, subj.getName()); return s; } }
结果:
Original Object: John - Algebra Cloned Object: John - Algebra Is Original Object the same with Cloned Object: false Is Original Object's field name the same with Cloned Object: true Is Original Object's field subj the same with Cloned Object: false Original Object after it is updated: Dan - Physics Cloned Object after updating original object: John - Algebra
四、延迟拷贝
延迟拷贝是浅拷贝和深拷贝的一个组合,实际上很少会使用。 当最开始拷贝一个对象时,会使用速度较快的浅拷贝,还会使用一个计数器来记录有多少对象共享这个数据。当程序想要修改原始的对象时,它会决定数据是否被共享(通过检查计数器)并根据需要进行深拷贝。
延迟拷贝从外面看起来就是深拷贝,但是只要有可能它就会利用浅拷贝的速度。当原始对象中的引用不经常改变的时候可以使用延迟拷贝。由于存在计数器,效率下降很高,但只是常量级的开销。而且, 在某些情况下, 循环引用会导致一些问题。
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- java中的浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- Java中的深复制与浅复制
- JAVA中浅复制与深复制
- JAVA中浅复制与深复制
- java 深复制与浅复制
- IOS 子视图touch,父视图Ges手势冲突问题解决方法
- Android Studio一步步教你集成发布适配
- layoutSubviews总结
- LeetCode总结2-Linked List
- 数据从HDFS导入hive
- JAVA 深复制与浅复制
- 简单网络命令
- 深入学习委托
- 2009: C语言实验——各位数字之和排序
- iOS程序猿之使用GitHub完成一次项目开发
- 解题报告:Radar Installation 一道贪心,不算难
- Struts2设置默认的action
- JS中实现字符串和数组的相互转化
- 51Nod 1119 机器人走方格 ——除法取模