java-clone、Serializable

 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 }
原文地址:https://www.cnblogs.com/holoyong/p/7519373.html