无法序列化已经序列化的类?

尼基尔·栗仓濑

请参阅下面的片段

    USPresident usPresident = new USPresident(56);
    try (ObjectOutputStream oos = new ObjectOutputStream(new
    FileOutputStream("/home/nikhil/dev/USPresident.data"))){
    oos.writeObject(usPresident);
    usPresident.setTerm(57);
    oos.writeObject(usPresident);
    System.out.println("Serialized");
    }

创建了一个任期为56的President实例。对其进行序列化。将该术语重置为57,再次对其进行序列化

但是,当我反序列化该对象时,它仍然具有术语56(而不是57!)。

我看了书就明白了

是的,即使您使用设置器将术语更改为57并再次序列化,它也会打印56。发生这种情况的原因是serialVersionUID,在序列化时由JVM检查了它。如果一个类已被序列化,而您尝试再次对其进行序列化,则JVM将不会对其进行序列化。

但是,据我了解,serialVersionUID用于检查反序列化过程中Class对象是否与序列化对象匹配。同样,serialVersionUID用作对象签名的标识符,而不是状态。

不明白这里发生了什么。有人可以解释这种行为吗?

看了ObjectOutputStream的实现,这就是writeObjet的实现方式

public final void writeObject(Object obj) throws IOException {
    if (enableOverride) {
        writeObjectOverride(obj);
        return;
    }
    try {
        writeObject0(obj, false);
    } catch (IOException ex) {
        if (depth == 0) {
            writeFatalException(ex);
        }
        throw ex;
    }
}

参见boolean enableOverride编写“修改”对象必须为真。但是,仅当使用将ObjectOutputStream子类化时,才可以将其设置为true。请参阅下面的受保护的构造函数,

protected ObjectOutputStream() throws IOException, SecurityException {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
    }
    bout = null;
    handles = null;
    subs = null;
    enableOverride = true;
    debugInfoStack = null;
}

为什么会有这种奇怪的行为?

克莱里斯-谨慎乐观-

您的书有误,而serialVersionUID静态的,则用于处理类本身的不同版本。

序列化的想法是获取一个活动对象(由指向的对象usPresident)并将其所有状态保存为某种外部形式(字节,XML,JSON)。然后,您可以将该状态转换回该对象的副本。就像将文件保存在文字处理器中一样。

但是,如果在序列化对象后修改该对象,则不会建立连接。您已经将字节写出到磁盘,并且它们不会更改,因为您在对象上调用了方法。当从这些字节重新创建对象时,该对象将具有与保存对象时相同的值。如果您忘记将更改保存到文字处理文档中,则磁盘上的文件仍然具有旧内容。

在您的情况下,您正在Java序列化中遇到一个怪癖,因为您将同一对象多次写入同一个对象ObjectOutputStream为了使您可以序列化复杂的对象关系,Java序列化仅将对象保存一次,然后在再次保存时链接回该对象。关闭并重新打开流,您应该看到更新的值。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章