最近这段时间太忙了。以至于之前一篇博文没办法写下去。
趁着今天早上有1个半小时的空闲,写一篇 深拷贝与浅拷贝
为什么要拷贝?
Java克隆是为了得到一个 完全一致的对象。
相同点:对象完全一样。这包括里头所有的变量,对象。
不同点:对象的内存地址不一样。
深拷贝与浅拷贝
一般来说,拷贝的类型分为 深拷贝与浅拷贝。
|—————————————————————————————|
| 深拷贝:引用对象的值等信息,复制一份一样的。 |
| 浅拷贝:只复制引用,另一处修改,你当下的对象也会修改。 |
|—————————————————————————————|
网上有这样的描述,以上描述不科学
从字面上理解更好。
浅拷贝---拷贝的级别浅。
深拷贝---拷贝级别更深。
具体呢?
浅拷贝---能复制变量,如果对象内还有对象,则只能复制对象的地址
深拷贝---能复制变量,也能复制当前对象的 内部对象
代码范例
public class mytest { public static void main(String[] args) { Parent item1 = new Parent("john", 10); Parent item2 = item1.clone(); System.out.println("parent1 = " + item1.toString()); System.out.println("parent2 = " + item2.toString()); } public static class Parent implements Cloneable{ String name = ""; int age = 0; Parent (String n, int age){ this.name = n; this.age = age; } public void setName(String na) { name = na; } @Override protected Parent clone() { Parent clone = null; try { clone = (Parent) super.clone(); } catch (CloneNotSupportedException e){ throw new RuntimeException(e); // won't happen } return clone; } public String toString() { return "Parent[" + name + "===" + age + "];"; } } }
测试结果:
parent1 = Parent[john===10]; parent2 = Parent[john===10];
Parent1被复制了一份。
修改下main函数
再执行一次。
测试结果:
发现parent1被修改了,但是parent2并未收到影响。
再修改一下.
添加一个内部类son,并加到parent里头去。
public class mytest { 。。。。。。。。 public static class Parent implements Cloneable{ String name = ""; int age = 0; Son theson; Parent (String n, int age){ this.name = n; this.age = age; } public void setName(String na) { name = na; } public void setSon(Son s) { theson = s; } @Override protected Parent clone() { Parent clone = null; try { clone = (Parent) super.clone(); } catch (CloneNotSupportedException e){ throw new RuntimeException(e); // won't happen } return clone; } public String toString() { return "Parent[" + name + "===" + age + "];" + "---Son:"+ (theson != null ? theson.name : "null"); } } public static class Son implements Cloneable { String name = ""; int age = 0; Son (String n, int age){ this.name = n; this.age = age; } public void setName(String na) { name = na; } @Override protected Son clone() { Son clone = null; try { clone = (Son) super.clone(); } catch (CloneNotSupportedException e){ throw new RuntimeException(e); // won't happen } return clone; } public String toString() { return "Son[" + name + "===" + age + "];"; } } }
<span style="mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;"> </span>
看main的修改
先copy再设置。
测试结果:
可以看到parent1与parent2中的son都变了。
可见,浅拷贝---只是将 内部对象的地址保存。。。。
最后,修改一下Clone
@Override protected Parent clone() { Parent clone = null; try { clone = (Parent) super.clone(); } catch (CloneNotSupportedException e){ throw new RuntimeException(e); // won't happen } clone.theson = theson.clone(); return clone; }
测试结果:
parent1 = Parent[alice-john===10];---Son:alice---john's son parent2 = Parent[john===10];---Son:john'son<span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;"> </span>
结果达到了我预计的结果。。。
小结
浅拷贝与深拷贝,一字之差,主要表明了拷贝的层次差别。
Object的clone方法,必须要实现Cloneable。
表明了,clone方法的实现要程序员自己来。。。
而深浅拷贝只是术语的区别。。。你怎么实现的就是怎么个定义。
1. 必须实现Cloneable
2. 要深拷贝,得注意对象的内部对象,也需要clone