Java 编写可序列化子类

Java 编写可序列化子类,java,serialization,Java,Serialization,我正在阅读J.Bloch的有效Java,现在我在读关于序列化的部分。他说 如果为继承而设计的类不可序列化,则 可能无法编写可序列化的子类。具体来说,it 如果超类不提供可访问的 无参数构造函数 我不明白那个限制。我在以下课程中尝试了这一点: private static class Base { private int i; private Object o; public Base(int i, Object o){ if(i == 0 || o =

我正在阅读J.Bloch的有效Java,现在我在读关于序列化的部分。他说

如果为继承而设计的类不可序列化,则 可能无法编写可序列化的子类。具体来说,it 如果超类不提供可访问的 无参数构造函数

我不明白那个限制。我在以下课程中尝试了这一点:

private static class Base {

    private int i;
    private Object o;

    public Base(int i, Object o){
        if(i == 0 || o == null)
            throw new IllegalArgumentException("The arguments are not accepted by this constructor");
        this.i = i;
        this.o = o;
    }

    private void readObjectNoData() throws InvalidObjectException{
        throw new InvalidObjectException("Stream data required");
    }
}

private static class Derived extends Base implements Serializable{

    public Derived(int i, Object o) {
        super(i, o);
    }

    private static final long serialVersionUID = 1L;
}
实际上,我可以序列化
派生的
的一个实例,但当我试图对其进行序列化时,我遇到了一个异常:

java.io.InvalidClassException: com.pack.age.SerializableTest$Derived; no valid constructor

你不能解释一下这些事情的意义吗?我不明白为什么在这种情况下他们需要无参数构造函数。

api也需要它:

要允许序列化不可序列化类的子类型,请 子类型可能负责保存和恢复状态 超类型的公共、受保护和(如果可访问)包的 领域。只有当类 它有一个可访问的无参数构造函数来初始化 阶级的状态。如果出现以下情况,则声明类可序列化是错误的 事实并非如此。错误将在运行时检测到

在反序列化过程中,不可序列化类的字段将 使用的public或protected no arg构造函数初始化 班级。不带参数的构造函数必须可被指定的子类访问 可序列化。可序列化子类的字段将被还原 从小溪里


从文件反序列化对象时,需要能够实例化该对象。如果您有多参数
构造函数
,您将不知道如何实例化它(传递给它什么)。

当Java创建
派生的
对象时(通过任何方式),它必须能够正确初始化
基本类的状态。使用
new-Derived(0,null)
时,
Derived
的构造函数知道要调用
Base
的哪个构造函数,以确保
Base
设置正确

反序列化对象时,Java不使用构造函数;它使用单独的后门机制来设置可序列化对象的状态。不过,在这种情况下,JVM不知道如何调用超类构造函数;它唯一能做的就是调用一个无参数构造函数(这样类就可以适当地初始化它自己的私有字段)


也许
Base
具有某种内部状态(保存在私有字段中),
派生的
无法看到。此状态未序列化(因为
Base
未实现
Serializable
),如果没有构造函数设置,则对象的
Base
部分可能处于不一致状态。

如果要反序列化对象,需要一个无参数构造函数,可以调用该构造函数

所以除了你的

public Base(int i, Object o)
添加一个无参数构造函数,如

public Base()

因为代码试图在内存中重建一个类,部分要求是它有一个无参数的公共构造函数