当前位置 : 主页 > 编程语言 > java >

从零开始读 Java 源码 第一章 接口篇 Serializable(1)

来源:互联网 收集:自由互联 发布时间:2022-07-13
1.1 未序列化类型子类进行序列化 1.1.1 序列化是什么 想知道这个问题的答案,就要先读序列化源码的第一段内容 一个类可序列化的开关,通过实现 java.io.Serializable 开启。如果一个类不


1.1 未序列化类型子类进行序列化

1.1.1 序列化是什么

想知道这个问题的答案,就要先读序列化源码的第一段内容

从零开始读 Java 源码 第一章 接口篇 Serializable(1)_序列化

一个类可序列化的开关,通过实现 java.io.Serializable 开启。如果一个类不实现这个接口就不能进行任何的序列化或者反序列化操作(IO之类的)。所有序列化类的子类型也是可以被序列化的。用于序列化的接口没有任何的属性或者方法,唯一的作用只是对在语义(semantic)上标识类是可序列化的。

整理一下关键信息:

  • 实现 Serializable ,相当于开启序列化开关
  • Serializable 序列化过程可传递,父类序列化,继承这个类的子类型也可被序列化
  • Serializable 接口内部没有属性和方法,它起到一个标识作用
  • 1.1.2 父类未实现序列化接口,子类实现序列化接口会发生什么?

    从零开始读 Java 源码 第一章 接口篇 Serializable(1)_子类_02

    允许未序列化类的子类进行序列化,当它的父类型的属性权限是 public, protected 或者(如果是的话)包,子类型可以承担存取父类型的职责。 子类型可以承担职责当且仅当这个类继承的父类有一个无参构造来初始化话类数据。如果没有达成这个条件会产生错误。这个错误将在运行时被发现(be detected)。

    整理一下关键信息:

  • 未序列化的子类允许序列化
  • 子类可承担存取父类职责
  • 父类未实现,子类实现这种情况,需要一个无参构造
  • 我们来试下,如果父类未实现序列化接口,子类实现了,没有无参构造会发生什么:

    public class A {
    private static final long serialVersionUID = 1L;
    protected int b;

    //显示下面这句就不会报错
    // public A(){}

    public A(int b){
    this.b = b;
    }
    public int getB() {
    return b;
    }

    public void setB(int b) {
    this.b = b;
    }

    @Override
    public String toString() {
    return "{b="+b+"}";
    }
    }public class B extends A implements Serializable {
    private int c;
    public B(int c){
    super(0);
    this.c = c;
    }

    @Override
    public String toString() {
    return "{b="+b+",c="+c+"}";
    }
    }import java.io.*;
    public class Main {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
    Main solution = new Main();

    A a = new B(4);
    a.setB(7);
    ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("E:/aa.txt")));
    oo.writeObject(a);

    //反序列化
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/aa.txt")));
    A person = (A) ois.readObject();
    System.out.println(person);
    }
    }

    从零开始读 Java 源码 第一章 接口篇 Serializable(1)_子类_03

    子类型可以承担职责当且仅当这个类继承的父类有一个无参构造来初始化类数据。

    尊重科学,给类型A加上无参构造试试:

    import com.dyy.jdk8.test.A;
    import java.io.*;
    public class Main {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
    Main solution = new Main();

    A a = new A();
    a.setB(7);
    ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("E:/aa.txt")));
    oo.writeObject(a);

    //反序列化
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/aa.txt")));
    A person = (A) ois.readObject();
    System.out.println(person);
    }
    }import java.io.Serializable;

    public class A implements Serializable {
    private static final long serialVersionUID = 988077679676L;
    private int b;

    public A(){}

    public int getB() {
    return b;
    }

    public void setB(int b) {
    this.b = b;
    }

    @Override
    public String toString() {
    return "{b="+b+"}";
    }
    }

    从零开始读 Java 源码 第一章 接口篇 Serializable(1)_子类_04

    OK,这一段搞定

    从零开始读 Java 源码 第一章 接口篇 Serializable(1)_后端_05

    在反序列化过程中,未序列化的类需要使用public或者protected级别的构造器进行初始化。没有参数的构造必须要有个对应可以序列化的子类。子类的属性在序列化的过程中将被保存在流中。

    这一段也很好理解,如果未序列化的类构造不是 public 或者 protected 级别的,就无法在序列化过程中被调用,这一段可以和前一段放在一起理解:

    如果子类序列化,父类不序列化,父类必须有public/protected 级别的无参构造。

    1.1.3 未实现 Serializable 接口,进行流的输入输出

    从零开始读 Java 源码 第一章 接口篇 Serializable(1)_序列化_06

    在遍历对象图的过程中,一个对象可能不支持序列化接口。

    这种情况下会对没有序列化的类型抛出 NotSerializableException 异常,让我们看下:

    从零开始读 Java 源码 第一章 接口篇 Serializable(1)_开发语言_07

    试一下把这里改成A的对象。

    从零开始读 Java 源码 第一章 接口篇 Serializable(1)_子类_08

    出现这个异常。

    1.1.4  小结

  • 如果一个类进行序列化,它的子类也会进行序列化
  • 如果一个类及其父类都未进行序列化,则进行IO操作过程,会产生异常
  • 如果一个类进行了序列化,它的父类没有进行序列化,则父类必须有一个无参的public/protected构造器,否则会产生异常
  • PS: 我不是一个高手,只是一个期望在枯燥的源码中找出点乐趣的普通人。英语很难,我的英语很差,参考百度翻译一段英语理解了很多次(其实有的部分,参考翻译还是看不太懂,就要不停的去想,去证实自己理解的对不对)。

    如果理解的不正确,欢迎读者骂我,达者为师,我尊师重道,感谢您的指导与批评!

    【转自:香港高防 http://www.558idc.com/stgf.html转载请说明出处】
    网友评论