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

标签 java serialization

请看下面的截图

    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!)

我在书中看到了这个解释,

Yes, it will print 56 even though you changed the term using its setter to 57 and serialized again. This happens due to serialVersionUID, which is checked by the JVM at the time of serialization. If a class is already serialized and you try to serialize it again, the JVM will not serialize it.

但是,据我了解,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 。这必须是真实的才能写“修改过的”对象。但是,这可以设置为 true,仅当使用确实子类化 ObjectOutputStream 时。请参阅下面的 protected 构造函数,

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是为了处理类本身的不同版本。

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

但是,如果在序列化后修改对象,则没有任何联系。您已经将字节写入磁盘,并且它们不会因为您调用对象上的方法而改变。当您从这些字节重新创建对象时,它将具有与保存时相同的值。如果您忘记保存对文字处理文档所做的更改,磁盘上的文件仍具有旧内容。

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

关于java - 无法序列化已经序列化的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26500655/

相关文章:

.net - 是否可以在具有 SOAP 对象的服务上使用多态性?

java - Android 中使用 MySQL/JDBC 时未找到 Throwable.initCause

java - 私有(private)方法的返回值

java - hibernate - 日期之间不起作用

java - 泽西警告 - 无法解析为具体类型

ajax - 如何让我的 JSON 不那么冗长?

Angular 2(或 4)对象序列化

.net - 将 C# 对象序列化为 XML - 最快的方法?

java - 如何禁用 JSpinner 的键盘和鼠标输入?

c# - 序列化和发送 Protocol Buffers 消息