16

我正在尝试序列化一个对象,然后在将其数据发送到客户端程序后对其进行反序列化。

这是对象继承如何工作的示例。我正在序列化和反序列化的对象是人。

生活 -> 动物 -> NPC -> 人 -> 儿童

Living、Animal 和 NPC 不实现 Serializable。我不能改变这三个类。Person 和 Child 确实实现了 Serializable。Person 和 Living 也是抽象类。我可以很好地序列化一个人(他是一个孩子)并发送它,但是当我尝试反序列化一个人(他是一个孩子)时,我在 Child 上得到一个 InvalidClassException,说“没有有效的构造函数”。

为什么会这样?Living、Animal 和 NPC 都必须实现 Serializable 吗?

4

3 回答 3

13

下面的问题Deserializing an ArrayList的答案中做了很好的解释 。没有有效的构造函数

长话短说-NPC在您的情况下,您的类的第一个不可序列化的超类需要无参数构造函数。

如果您无权访问 NPC 并且它不包含无参数构造函数 - 那么您可以在层次结构中再添加一个“假”类,该类将选择正确的类。例如

class SomeClass extends NPC {
// will be called during deserialization
public SomeClass(){
// call custom constructor of NPC
super(null);
}
}

class Person extends SomeClass implements Serializable {
// ..
}
于 2012-08-25T19:50:54.970 回答
2

根据这个线程,它们不需要实现可序列化,但它们(或至少 NPC,因为它是层次结构中的第一个不可序列化类)必须包含一个 0 参数构造函数。如果类中没有定义构造函数,则隐式构造函数就足够了,但如果在这些类中定义了其他构造函数,则必须编写显式的 0 参数构造函数。

由于您无法控制 NPC,因此请尝试创建定义显式 0 参数构造函数但不实现 Serializable 的它的子代,并查看是否不这样做。

于 2012-08-25T19:56:11.597 回答
0

我在Hazelcast的序列化中遇到了同样的问题,但是通过使用自定义序列化解决了这个问题,而无需借助中间类。我向 Animal 类添加了一个空的无参数构造函数,并实现了 Person 类,如下所示:

class Person extends Animal implements Serializable {

    private void writeObject(ObjectOutputStream o) throws IOException {
        o.writeObject(this.fieldA);
        o.writeObject(this.fieldB);
        o.writeObject(this.fieldC);
        ...
    }

    private void readObject(ObjectInputStream o) throws IOException, ClassNotFoundException {
        this.fieldA = (TypeOfA) o.readObject();
        this.fieldB = (TypeOfB) o.readObject();
        this.fieldC = (TypeOfC) o.readObject();
        ...
    }
}
于 2015-06-16T18:40:30.040 回答