当只有子类实现可序列化时,序列化的工作原理

只有子类具有实现的接口。Serializable

import java.io.*;

public class NewClass1{

    private int i;
    NewClass1(){
    i=10;
    }
    int getVal() {
        return i;
    }
    void setVal(int i) {
        this.i=i;
    }
}

class MyClass extends NewClass1 implements Serializable{

    private String s;
    private NewClass1 n;

    MyClass(String s) {
        this.s = s;
        setVal(20);
    }

    public String toString() {
        return s + " " + getVal();
    }

    public static void main(String args[]) {
        MyClass m = new MyClass("Serial");
        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("serial.txt"));
            oos.writeObject(m); //writing current state
            oos.flush();
            oos.close();
            System.out.print(m); // display current state object value
        } catch (IOException e) {
            System.out.print(e);
        }
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("serial.txt"));
            MyClass o = (MyClass) ois.readObject(); // reading saved object
            ois.close();
            System.out.print(o); // display saved object state
        } catch (Exception e) {
            System.out.print(e);
        }
    }
}

我在这里注意到的一件事是,父类没有序列化。那么,为什么它没有抛出它确实显示以下内容NotSerializableException

输出

Serial 20
Serial 10

此外,输出与 和 不同。我才知道,是因为父类没有实现。但是,如果有人解释我,在对象序列化和反序列化期间会发生什么。它如何改变值?我无法弄清楚,我也在我的程序中使用了注释。所以,如果我在任何时候都错了,请告诉我。SerializationDe-serializationSerializable


答案 1

根据可序列化的javadoc

在反序列化期间,不可序列化类的字段将使用类的公共或受保护的 no-arg 构造函数进行初始化。无 arg 构造函数必须可供可序列化的子类访问。可序列化的子类的字段将从流中恢复。

此外,仅当正在序列化的类不可序列化时,才会引发序列化异常。具有不可序列化的父项是可以的(只要它们具有无参数构造函数)。对象本身是不可序列化的,所有内容都扩展了它。上面的引号还解释了为什么你为值字段获得不同的值 - 设置了父类的no-arg构造函数,它将值字段设置为10 - 该字段属于(不可序列化的)父项,因此其值不会写入/读取流。


答案 2

如果您的 MyClass 包含对不可序列化类的对象的引用,您将在运行时收到不可序列化异常。若要进行测试,请修改 MyClass,使其包含对 NewClass1 对象的引用。如果再次运行,它将引发异常。

反序列化实质上是创建可序列化类的实例并还原其属性。在此过程中,不调用可序列化类的构造函数。而是调用第一个不可序列化的超类的无 arg 构造函数。

在你的例子中,NewClass1 的 no arg 构造函数将 10 分配给其实例变量 i。因此,在反序列化期间,它打印 10 而不是 20。