clone
1 public class TempClazz { 2 public static void main(String[] args) throws CloneNotSupportedException { 3 A original = new A(); 4 original.a = 1; 5 original.b = new B(); 6 original.b.b = 2; 7 A clone = (A) original.clone(); 8 clone.a = 3; 9 clone.b.b = 4; 10 System.out.println("original: " + original); 11 System.out.println("clone: " + clone); 12 } 13 14 private static class A implements Cloneable{ 15 private int a; 16 private B b; 17 18 @Override 19 protected Object clone() throws CloneNotSupportedException { 20 return super.clone();//Object的clone方法为native方法 21 } 22 23 @Override 24 public String toString() { 25 return "A{" + 26 "a=" + a + 27 ", b=" + b + 28 '}'; 29 } 30 } 31 private static class B { 32 private int b; 33 34 @Override 35 public String toString() { 36 return "B{" + 37 "b=" + b + 38 '}'; 39 } 40 } 41 }
输出
original: A{a=1, b=B{b=4}} clone: A{a=3, b=B{b=4}}
由输出可知,Object.clone()是浅赋值,只会复制最外层的基础类型和引用(会复制transient字段,类字段不需要复制),并且只需要最外层类实现标记接口Cloneable即可。
当然,可以实现自己的clone方法,最简单的就是返回对象本身,不使用Object.clone()就不必实现Cloneable接口了。
1 @Override 2 protected Object clone() throws CloneNotSupportedException { 3 return this; 4 }
如果要实现深度复制,可以使用序列化工具,先将对象序列化,然后再反序列化,比如json,也可以实现自己的深度复制逻辑,创建一个新实例,递归遍历字段进行赋值。
Serializable
1 public void SerializableTest() throws IOException, ClassNotFoundException { 2 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 3 ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 4 SerA serA = new SerA(); 5 serA.a = 1; 6 serA.b = new B(); 7 serA.b.b = 2; 8 serA.c = 3; 9 serA.d = 4; 10 objectOutputStream.writeObject(serA); 11 objectOutputStream.close(); 12 13 serA.c = 9; 14 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); 15 ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); 16 Object object = objectInputStream.readObject(); 17 System.out.println(object); 18 objectInputStream.close(); 19 } 20 21 private static class SerA implements Serializable { 22 23 private int a; 24 private B b; 25 private static int c; 26 private transient int d; 27 28 @Override 29 public String toString() { 30 return "SerA{" + 31 "a=" + a + 32 ", b=" + b + 33 ", c=" + SerA.c + 34 ", d=" + d + 35 '}'; 36 } 37 } 38 39 private static class B implements Serializable{ 40 private int b; 41 42 @Override 43 public String toString() { 44 return "B{" + 45 "b=" + b + 46 '}'; 47 } 48 }
输出
SerA{a=1, b=B{b=2}, c=9, d=0}
由输出可以看出,java序列化会屏蔽transient字段和静态字段,最外层类需要实现Serializable接口,且字段类也需要实现Serializable接口。
要实现自己的序列化逻辑,只需要在被序列化类中添加readObject和writeObject方法
1 private void writeObject(java.io.ObjectOutputStream out){//...} 2 private void readObject(java.io.ObjectInputStream in){//...}
ObjectOutputStream和ObjectInputStream会调用这两个方法
1 //序列化 2 //slotDesc是ObjectStreamClass类型 3 if (slotDesc.hasWriteObjectMethod()) { 4 //... 5 //如果该要序列化的class存在writeObject方法,则调用 6 slotDesc.invokeWriteObject(obj, this); 7 //... 8 } 9 10 //反序列化 11 //从流中读取class信息 12 ObjectStreamClass desc = readClassDesc(false); 13 //... 14 //slotDesc是ObjectStreamClass类型 15 if (slotDesc.hasReadObjectMethod()) { 16 //... 17 //如果该要序列化的class存在readObject方法,则调用 18 slotDesc.invokeReadObject(obj, this); 19 //... 20 }