Cloneable 和clone的区别和联系
设计模式----原型模式时候,涉及到的复制克隆,
Cloneable 接口,内部是没有任何方法的,
这个接口其实是一个标记性的接口,和Serializable是一样的,都是标记使用,
在类实现了这个Cloneable 接口后调用Object中得clone方法,才可以正常的使用,如果没有implements Cloneable的类调用Object.clone()方法就会抛出CloneNotSupportedException。
在复制中,分为浅复制和深复制;
先说浅复制:
其实这样的复制是一种很危险的复制,有时候预期效果并不是你想要的!
1 package Method.clone; 2 3 public class Student implements Cloneable 4 { 5 private int id; 6 private String name; 7 public StringBuffer sb = new StringBuffer(""); 8 9 public Student() { 10 this.id = 744; 11 this.name = "FL"; 12 } 13 14 public Student(int id, String name) { 15 this.id = id; 16 this.name = name; 17 } 18 19 public boolean equals(Object obj) { 20 return this.id == ((Student) obj).id; 21 } 22 23 public String toString() { 24 return "Student id : " + id + " Name " + name; 25 } 26 27 public static void main(String[] args) throws CloneNotSupportedException // 这里为什么一定得写 28 { 29 Student s1 = new Student(101, "WangQiang"); 30 Student s2 = (Student) s1.clone(); 31 System.out.println(s1 == s2); 32 System.out.println(s1); 33 System.out.println(s2); 34 35 s1.sb.append("s1's string"); 36 System.out.println("s2.sb's value = " + s2.sb.toString()); 37 System.out.println(s1.sb==s2.sb); 38 39 } 40 }
浅层拷贝导致s1和s2共享同一个StringBuffer对象,s2还是可以调用s1中得StringBuffer。这样的复制还是很危险!
Object中提供的clone方法是一种浅复制,对于基本类型的字段,可以说它成功克隆了。但对于对象型字段,它并没有实现克隆的功能,仅仅做了一个赋值。(拷贝基本成员属性,对于引用类型仅返回指向改地址的引用)
深复制:
首先这个对象必须实现了Serializable 接口,可以被序列化,和反序列化:深复制时候采用的是流进行读写的,原对象还是存在JVM中
序列化前和序列化后的对象的关系
反序列化还原后的对象地址与原来的的地址不同,序列化前后对象的地址不同了,但是内容是一样的,而且对象中包含的引用也相同。换句话说,通过序列化操作,我们可以实现对任何可Serializable对象的”深度复制(deep copy)"——这意味着我们复制的是整个对象网,而不仅仅是基本对象及其引用。对于同一流的对象,他们的地址是相同,说明他们是同一个对象,但是与其他流的对象地址却不相同。也就说,只要将对象序列化到单一流中,就可以恢复出与我们写出时一样的对象网,而且只要在同一流中,对象都是同一个。
1 public Object deepClone() throws IOException, ClassNotFoundException{ 2 //将对象写到流里 3 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 4 ObjectOutputStream oos = new ObjectOutputStream(bos); 5 oos.writeObject(this); 6 //从流里读回来 7 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); 8 ObjectInputStream ois = new ObjectInputStream(bis); 9 return ois.readObject(); 10 }
对具体分析:参考博客
http://www.cnblogs.com/tonyluis/p/5779187.html