zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    二分专题
    数据结构-图
    Linux文件基本属性(以ls -l输出为例解释)
    shell脚本版素数筛
    Linux whereis,which
    Linux外网代理配置
    Linux三剑客
    Elasticsearch集群搭建(Linux)
    测试之路
    我的另一半
  • 原文地址:https://www.cnblogs.com/holoyong/p/7519373.html
Copyright © 2011-2022 走看看