Java里的浅复制与深复制
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不
复制它所引用的对象。
⑵深复制(深克隆) 被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原
有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
2.Java的clone()方法 ⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足: ①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象 ②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样 ③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
⑵Java中对象的克隆 ①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。 ②在派生类中覆盖基类的clone()方法,并声明为public。 ③在派生类的clone()方法中,调用super.clone()。 ④在派生类中实现Cloneable接口。
请看如下代码:
class Student implements Cloneable { String name; int age; Student(String name,int age) { this.name=name; this.age=age; } public Object clone() { Object o=null; try { o=(Student)super.clone();//Object 中的clone()识别出你要复制的是哪一个对象。 } catch(CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } public static void main(String[] args) { Student s1=new Student("zhangsan",18); Student s2=(Student)s1.clone(); s2.name="lisi"; s2.age=20; System.out.println("name="+s1.name+","+"age="+s1.age);//修改学生2后,不影响学生1的值。 }
说明: ①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。 ②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。
class Professor { String name; int age; Professor(String name,int age) { this.name=name; this.age=age; } } class Student implements Cloneable { String name;// 常量对象。 int age; Professor p;// 学生1和学生2的引用值都是一样的。 Student(String name,int age,Professor p) { this.name=name; this.age=age; this.p=p; } public Object clone() { Student o=null; try { o=(Student)super.clone(); } catch(CloneNotSupportedException e) { System.out.println(e.toString()); } o.p=(Professor)p.clone(); return o; } } public static void main(String[] args) { Professor p=new Professor("wangwu",50); Student s1=new Student("zhangsan",18,p); Student s2=(Student)s1.clone(); s2.p.name="lisi"; s2.p.age=30; System.out.println("name="+s1.p.name+","+"age="+s1.p.age);//学生1的教授成为lisi,age为30。 }
那应该如何实现深层次的克隆,即修改s2的教授不会影响s1的教授?代码改进如下。
改进使学生1的Professor不改变(深层次的克隆) class Professor implements Cloneable { String name; int age; Professor(String name,int age) { this.name=name; this.age=age; } public Object clone() { Object o=null; try { o=super.clone(); } catch(CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } class Student implements Cloneable { String name; int age; Professor p; Student(String name,int age,Professor p) { this.name=name; this.age=age; this.p=p; } public Object clone() { Student o=null; try { o=(Student)super.clone(); } catch(CloneNotSupportedException e) { System.out.println(e.toString()); } o.p=(Professor)p.clone(); return o; } } public static void main(String[] args) { Professor p=new Professor("wangwu",50); Student s1=new Student("zhangsan",18,p); Student s2=(Student)s1.clone(); s2.p.name="lisi"; s2.p.age=30; System.out.println("name="+s1.p.name+","+"age="+s1.p.age);//学生1的教授不 改变。 } 3.利用串行化来做深复制 把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做 “解冻”或者“回鲜(depicking)”过程。
应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。 在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。 如下为深复制源代码。 public Object deepClone() { //将对象写到流里 ByteArrayOutoutStream bo=new ByteArrayOutputStream(); ObjectOutputStream oo=new ObjectOutputStream(bo); oo.writeObject(this); //从流里读出来 ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi=new ObjectInputStream(bi); return(oi.readObject()); }
这样做的前提是对象以及对象内部所有引用到的对象都是可串行化的,否则,就需要仔细考察那些不可串行化的对象可否设成transient,从而将之排除在复制过程之外。上例代码改进如下。 class Teacher implements Serializable{ String name; int age; Teacher(String name,int age){ this.name=name; this.age=age; } } class Student implements Serializable{ String name;//常量对象 int age; Teacher t;//学生1和学生2的引用值都是一样的。 Student(String name,int age,Teacher t){ this.name=name; this.age=age; this.p=p; } public Object deepClone() throws IOException, OptionalDataException,ClassNotFoundException{//将对象写到流里 ByteArrayOutoutStream bo=new ByteArrayOutputStream(); ObjectOutputStream oo=new ObjectOutputStream(bo); oo.writeObject(this);//从流里读出来 ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi=new ObjectInputStream(bi); return(oi.readObject()); }
} public static void main(String[] args){ Teacher t=new Teacher("tangliang",30); Student s1=new Student("zhangsan",18,t); Student s2=(Student)s1.deepClone(); s2.t.name="tony"; s2.t.age=40; System.out.println("name="+s1.t.name+","+"age="+s1.t.age);//学生1的老师不改变 }
Java里的浅复制与深复制的更多相关文章
- JAVA中浅复制与深复制 - coolmist - ITeye技术网站
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- JAVA中浅复制与深复制
1.浅复制与深复制概念⑴浅复制(浅克隆)被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵深复 ...
- java基础-浅复制与深复制的理解
浅复制与深复制在很多编程语言中都有出现,那么什么是浅复制,什么是深复制呢? 要区分浅复制与深复制,首先我们要明确什么是复制,怎样才算是复制.复制的例子在生活中也随处可见,如复印一份文档,复制一段文字等 ...
- Java中引用的浅复制和深复制
Java中除了基本类型int,char,double等的赋值是按照值传递之外,其余的类型和对象都是按照引用进行传递的. 下面来看一个关于引用的例子. package referenceCopy;// ...
- Java中的“浅复制”与“深复制”
复制 将一个对象的引用复制给另一个对象,一共有三种方式.第一种方式是直接赋值,第二种方式是浅复制,第三种方式是深复制. 1.直接赋值 在Java中,A a1 = a2,这实际上复制的是引用,也就是说 ...
- php对象复制、clone、浅复制与深复制实例详解
php对象复制.clone.浅复制与深复制实例详解 一.用clone(克隆)来复制对象$obj1 = new Object();$obj2 = clone $obj1;clone方法会触发对象里定义的 ...
- iOS 浅复制和深复制的深层理解,含示例
转载:https://www.zybuluo.com/MicroCai/note/50592 版权归 @MicroCai 所有 以下是正文: 浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅复制 ( ...
- iOS 浅赋值、深复制、全然复制的知识点梳理验证(附加归档解档)
写于前: 在之前转载的一片文章中.文中对浅复制和深复制进行了具体的解读,同一时候还提到了深复制(one-level-deep copy).全然复制(true copy)的概念,并指出iOS开发中的深复 ...
- 设计模式-原型模式(Prototype)【重点:浅复制与深复制】
讲故事 最近重温了一下星爷的<唐伯虎点秋香>,依然让我捧腹不已,幻想着要是我也能有一名秋香如此的侍女,夫复何求呀,带着这个美好的幻想沉沉睡去... 突然想到,我是一名程序猿呀,想要什么对象 ...
随机推荐
- Qt 设置应用程序图标(windows)
Step 1: 创建 xxx.rc 文件. 将ico图标文件复制到项目根目录下.然后在该目录中新建xxx.rc文件,并输入一行代码: IDI_ICON1 ICON DISCARDABLE " ...
- notepad++中快速插入当前时间方法
转载自:http://blog.csdn.net/donghustone/article/details/7436483 在notepad++中快速插入当前时间方法: 插件是notepad++的一大优 ...
- HTML5学习之新增标签
转自:http://www.cnblogs.com/fly_dragon/archive/2012/05/25/2516142.html 作者:FlyDragon 一.引言 在本节中,笔者将向大家讲述 ...
- [转载]超赞!32款扁平化Photoshop PSD UI工具包(下)
32款扁平化风格的UI工具包第二弹!上篇为大家分享了16款风格各异的UI Kits,下篇继续为大家呈上16款精美的UI工具包,全部都有Photoshop PSD文件可以下载哦,喜欢就赶紧收藏吧! 17 ...
- C# ICSharpCode.SharpZipLib.Zip 的使用
public static class ZipFileHelper { #region 加压解压方法 /// <summary> /// 功能:压缩文件(暂时只压缩文件夹下一级目录中的文件 ...
- Ubuntu 下nginx 的卸载 与重新装
由于本人把自己服务器的nginx 给玩坏了,不得已选择卸载重新安装,(先让我哭一会) 然后我把/usr/sbin/nginx 和/etc/nginx 和/usr/share/nginx 和 /usr ...
- CentOS 7 部署nginx
**二进制安装 安装Nginx源 rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el ...
- CentOS 7 安装python3.6.1
说明:CentOS 7最小化安装,默认Python 2.7 ,开发需要安装python3.6.1 . 1.检查python版本 [root@bogon ~]# python -VPython 2.7. ...
- algorithm ch7 QuickSort
快速排序是基于分治模式的排序,它将数组a[p,...,r]分成两个子数组a[p,...q-1],a[q+1,...,r],使得a[p,...,q-1]中每个元素都小于a[q],而且小于等于a[q+1, ...
- Getting or Setting Pixels
Getting or Setting Pixels The safe (slow) way Suppose you are working on an Image<Bgr, Byte>. ...