首页 / JAVA / Java的“影子克隆”和“深度克隆”
Java的“影子克隆”和“深度克隆”
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java的“影子克隆”和“深度克隆”,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3922字,纯文字阅读大概需要6分钟。
内容图文
今天来学习学习java对象的克隆,在写代码的时候,有时候我们会这样写:对象1=对象2,也就是把对象2赋值给对象1了,但是这样做有个问题,就是如果我们修改了对象2的属性值,对象1的相同属性值也被修改了,反过来亦如此,让我来证明一下:
public class A { private String msg; public A() { msg = "Hello"; } public String getMsg() { return msg; } publicvoid setMsg(String msg) { this.msg = msg; } }
public class Main { public static void main(String[] args) { A a1 = new A(); A a2 = new A(); System.out.println("a1.msg: " + a1.getMsg()); a1 = a2; a2.setMsg("World"); System.out.println("a1.msg: " + a1.getMsg()); } }
运行结果:
从Main类可以看到,一开始我们new了两个对象,也就是在JVM堆内存开辟了两块内存空间,接着把a2赋值给a1,这就意味着a2和a1对象指向了栈内存中同一个引用,这个时候我们修改a2对象的属性,a1对象的属性也同时会改变,反过来亦如此,例如我现在修改a1的属性来试试看a2的属性是否被改变了:
public class Main { public static void main(String[] args) { A a1 = new A(); A a2 = new A(); System.out.println("a1.msg: " + a1.getMsg()); a1 = a2; a1.setMsg("Java"); System.out.println("a2.msg: " + a2.getMsg()); } }
毫无悬念地改变了,也就是说使用“=”操作符会让两个对象指向同一个引用,两个对象的属性值是互通的,一个对象的改变必然会同步到另一个对象上面,但是有时候我们并不想一个对象的改变引起另一个对象的改变,我们希望a2对象被创建后含有a1对象初始的值,但是a2对象属性的改变不会影响a1对象,这样我们就应该使用对象的克隆,对象的克隆又分浅克隆和深克隆,我们先来看看浅克隆的实现方式:
public class A implements Cloneable { private String msg; public A() { msg = "Hello"; } public String getMsg() { return msg; } publicvoid setMsg(String msg) { this.msg = msg; } @Override protected Object clone() throws CloneNotSupportedException { returnsuper.clone(); } }
public class Main { public static void main(String[] args) throws CloneNotSupportedException { A a1 = new A(); System.out.println("a1.msg: " + a1.getMsg()); A a2 = (A) a1.clone(); System.out.println("a2.msg: " + a2.getMsg()); a2.setMsg("Java"); System.out.println("a1.msg: " + a1.getMsg()); System.out.println("a2.msg: " + a2.getMsg()); } }
可以看到实现对象的克隆比较简单,首先该类应该实现Cloneable接口并覆盖Object根类的clone方法,注意Cloneable只是一个标记接口,里面并没有定义任何方法,clone方法里面的实现也很简单,调用父类Object的clone方法就好了。现在看看Main类就知道,a2对象的msg初始化是"Hello",把a2的msg属性的值改为"Java"后,并没有影响a1对象的msg值,其值仍然是"Hello". 我们刚才看到的是浅克隆,没有集合属性,如果有集合属性的话,浅克隆就应付不了这种情况了,我们来看看代码:
public class A implements Cloneable { private List<String> list; public A() { list = new ArrayList<String>(); list.add("Hello"); list.add("World"); } public List<String> getList() { return list; } publicvoid setList(List<String> list) { this.list = list; } @Override protected Object clone() throws CloneNotSupportedException { returnsuper.clone(); } }
public class Main { public static void main(String[] args) throws CloneNotSupportedException { A a1 = new A(); System.out.println("a1.list: " + a1.getList()); A a2 = (A) a1.clone(); System.out.println("a2.list: " + a2.getList()); a2.getList().add("Java"); System.out.println("a1.list: " + a1.getList()); System.out.println("a2.list: " + a2.getList()); } }
大家看看,神奇的魔咒又出现了,即使我们实现了对象的克隆,但是因为对象的属性是集合类,这样我们修改a2对象的集合类中的值,也一定会影响a1对象集合类的值, 这是因为a1和a2对象的list属性是指向同一个内存地址的,面对这种情况,我们需要使用到对象的深克隆,具体怎么实现呢,来看代码:
public class A implements Cloneable { private List<String> list; public A() { list = new ArrayList<String>(); list.add("Hello"); list.add("World"); } public List<String> getList() { return list; } publicvoid setList(List<String> list) { this.list = list; } @Override protected A clone() throws CloneNotSupportedException { A other = (A) super.clone(); List<String> otherList = new ArrayList<String>(); for (String s : list) { otherList.add(s); } other.setList(otherList); return other; } }
public class Main { public static void main(String[] args) throws CloneNotSupportedException { A a1 = new A(); System.out.println("a1.list: " + a1.getList()); A a2 = (A) a1.clone(); System.out.println("a2.list: " + a2.getList()); a2.getList().add("Java"); System.out.println("a1.list: " + a1.getList()); System.out.println("a2.list: " + a2.getList()); } }
大家可以看到,深克隆的实现也就是要在clone方法里面new一个list,并把原来对象list中的值赋值到新list中并把新list设置到新对象,说起来好拗口啊,这样a2.list值得改变不会影响a1.list了,想想如果原始类的属性是一个对象,而对象的属性又有对象和集合类,那么clone方法里面的代码就会很大,因为深克隆必须保证全面的克隆。
原文:http://www.cnblogs.com/stonefeng/p/5808178.html
内容总结
以上是互联网集市为您收集整理的Java的“影子克隆”和“深度克隆”全部内容,希望文章能够帮你解决Java的“影子克隆”和“深度克隆”所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。