java 深克隆及浅克隆
来源:互联网 发布:铸造行业 利润 知乎 编辑:程序博客网 时间:2024/06/05 17:17
我继续在看java的基础知识,刚看完java的深克隆及浅克隆,就写篇博客记录下。
应用场景:
1.有时候,你需要克隆一个对象,但是对新克隆的对象的操作不会影响原对象。
2. 了解下深克隆,浅克隆,对java加深了解。
//对象引用的复制
Person p = new Person(23, "zhang");Person p1 = p;System.out.println(p);System.out.println(p1);结果是:test.deepClone.Person@2a84aee7test.deepClone.Person@2a84aee7可以看出来两个对象的内存地址是一样的。那肯定是一个对象。p,p1只是两个引用而已。都指向了一个对象,可以把这种现象叫做引用的复制。
//对象的拷贝
Person p = new Person(23, "zhang");Person p1 = (Person) p.clone();System.out.println(p);System.out.println(p1);结果是:test.deepClone.Person@2a84aee7test.deepClone.Person@a09ee92打印出不同的内存地址。说明实现了对象的克隆。
//person 类public class Person implements Cloneable{ private int age; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Person(int age, String name){ this.age = age; this.name = name; } protected Object clone() throws CloneNotSupportedException { return (Person)super.clone(); }}
记得实现Cloneable接口
我们为什么要实现Cloneable接口呢?其实Cloneable接口仅仅是一个标志,而且这个标志也仅仅是针对 Object类中 clone()方法的,如果 clone 类没有实现 Cloneable 接口,并调用了 Object 的 clone() 方法(也就是调用了 super.Clone() 方法),那么Object 的 clone() 方法就会抛出 CloneNotSupportedException 异常。
下面我再举例子来说明
public class MyTestCloneAbnormal implements Cloneable { private String name; private Email email; public String getName() { return name; } public void setName(String name) { this.name = name; } public MyTestCloneAbnormal(String name, Email email) { this.name = name; this.email = email; } public Object clone() throws CloneNotSupportedException { //返回clone的对象 return (MyTestCloneAbnormal) super.clone(); } static class Email implements Cloneable{ private String contet; private String title; public String getContet() { return contet; } public void setContet(String contet) { this.contet = contet; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Email(String title, String content) { this.title = title; this.contet = content; } } public static void main(String[] args) throws CloneNotSupportedException { MyTestCloneAbnormal p = new MyTestCloneAbnormal("yu", new Email("9.6中午会议", "今天中午十二点,大家在3楼会议室开会")); MyTestCloneAbnormal p1 = (MyTestCloneAbnormal) p.clone(); p1.setName("张三"); MyTestCloneAbnormal p2 = (MyTestCloneAbnormal) p.clone(); p2.setName("李四"); System.out.println("给[ " + p.getName() + " ]的邮件: " + p.email.getTitle() + "正文是:[" + p.email.getContet() + "]"); System.out.println("给[ " + p1.getName() + " ]的邮件: " + p1.email.getTitle() + "正文是:[" + p1.email.getContet() + "]"); System.out.println("给[ " + p2.getName() + " ]的邮件: " + p2.email.getTitle() + "正文是:[" + p2.email.getContet() + "]"); }}
我是看的一个教程写的。如果你要给三个员工发邮件。clone p对象。得到p1,p2,打印的结果是:
给[ yu ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]给[ 张三 ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]给[ 李四 ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]
如果我想让 yu早来半个小时,这个时候main方法是
public static void main(String[] args) throws CloneNotSupportedException { MyTestCloneAbnormal p = new MyTestCloneAbnormal("yu", new Email("9.6中午会议", "今天中午十二点,大家在3楼会议室开会")); MyTestCloneAbnormal p1 = (MyTestCloneAbnormal) p.clone(); p1.setName("张三"); MyTestCloneAbnormal p2 = (MyTestCloneAbnormal) p.clone(); p2.setName("李四"); System.out.println("给[ " + p.getName() + " ]的邮件: " + p.email.getTitle() + "正文是:[" + p.email.getContet() + "]"); System.out.println("给[ " + p1.getName() + " ]的邮件: " + p1.email.getTitle() + "正文是:[" + p1.email.getContet() + "]"); System.out.println("给[ " + p2.getName() + " ]的邮件: " + p2.email.getTitle() + "正文是:[" + p2.email.getContet() + "]"); //给p对象设置email内容 p.email.setContet("yu,你需要早到半小时"); System.out.println("给[ " + p.getName() + " ]的邮件: " + p.email.getTitle() + "正文是:[" + p.email.getContet() + "]"); System.out.println("给[ " + p1.getName() + " ]的邮件: " + p1.email.getTitle() + "正文是:[" + p1.email.getContet() + "]"); System.out.println("给[ " + p2.getName() + " ]的邮件: " + p2.email.getTitle() + "正文是:[" + p2.email.getContet() + "]");}
结果如下所示,
给[ yu ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]给[ 张三 ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]给[ 李四 ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]给[ yu ]的邮件: 9.6中午会议正文是:[yu,你需要早到半小时]给[ 张三 ]的邮件: 9.6中午会议正文是:[yu,你需要早到半小时]给[ 李四 ]的邮件: 9.6中午会议正文是:[yu,你需要早到半小时]
张三,李四的邮件内容也变了。。这就说明,关于对象clone,clone的是对象的引用。而不是clone的对象,这三个对象的email对象指向同一个地址。也就是所谓的浅克隆。
如果要实现深克隆,需要在克隆MyTestCloneAbnormal 类的时候,在MyTestCloneAbnormal类的clone处,克隆Email类。在Email类中也实现clone方法。代码如下所示。
MyTestCloneAbnormal类的clone方法public Object clone() throws CloneNotSupportedException { //返回clone的对象// return (MyTestCloneAbnormal) super.clone(); MyTestCloneAbnormal newp = (MyTestCloneAbnormal) super.clone(); newp.email = (Email)email.clone(); return newp; }Email的clone类@Overrideprotected Object clone() throws CloneNotSupportedException { return (Email) super.clone();}
结果如下所示:
给[ yu ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]给[ 张三 ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]给[ 李四 ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]给[ yu ]的邮件: 9.6中午会议正文是:[yu,你需要早到半小时]给[ 张三 ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]给[ 李四 ]的邮件: 9.6中午会议正文是:[今天中午十二点,大家在3楼会议室开会]
这就说明,我们实现了上面三个对象的Email对象深克隆,三个对象的Email对象都是指向了不同的内存地址,所以说,上面我们对p的改动才没有影响到其他两个p1,p2对象的Email属性。
其实出现问题的关键就在于clone()方法上,我们知道该clone()方法是使用Object类的clone()方法,但是该方法存在一个缺陷,它并不会将对象的所有属性全部拷贝过来,而是有选择性的拷贝,基本规则如下:
1、 基本类型 如果变量是基本很类型,则拷贝其值,比如int、float等。2、 对象 如果变量是一个实例对象,则拷贝其地址引用,也就是说此时新对象与原来对象是公用该实例变量。3、 String字符串 若变量为String字符串,则拷贝其地址引用。但是在修改时,它会从字符串池中重新生成一个新的字符串,原有紫都城对象保持不变。
还有一种通过字节流拷贝的方式,有兴趣可以自己去搜下。
参考的文章列表
http://blog.csdn.net/chenssy/article/details/12952063(他贴的代码有点问题,其他的还ok)
http://blog.csdn.net/zhangjg_blog/article/details/18369201/
- java 深克隆及浅克隆
- Java深克隆浅克隆
- java深克隆浅克隆
- Java浅克隆深克隆
- Java深克隆和浅克隆的原理及实现
- java 对象克隆 及深克隆 浅克隆 及Cloneable接口
- java的克隆(深克隆和浅克隆)
- java对象克隆(浅克隆和深克隆)
- JAVA之路_假克隆、浅克隆、深克隆
- Java中的假克隆、浅克隆、深克隆
- Java对象克隆方法(浅克隆、深克隆)
- Java对象克隆方法(浅克隆、深克隆)
- java克隆之深克隆和浅克隆
- 浅克隆、深克隆
- 深克隆,浅克隆
- java 深克隆与浅克隆
- java 深克隆与浅克隆 .
- java深克隆和浅克隆
- cglib-XXX.jar的下载与安装
- Visual Studio 2013下配置Opencv3.2 和CMAKE问题
- CS50 2016-Week 1 学习笔记
- 利用ROS系统实现工业机器人的控制
- 盒马鲜生创意总监做客阿里双创平台,首度解析“河马”品牌设计的前世今生
- java 深克隆及浅克隆
- Linux 下载和安装JDK
- 读取csv文件转化为Json
- 链表问题合集
- dotnet core publish and run
- 函数柯里化
- activity的launchmode和taskAffinity学习笔记(二)
- StoryBoard segue 用法
- 使用Go实现了一个ping命令