加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 04:44:27 所属栏目:Java 来源:网络整理
导读:请参阅下面的剪辑 USPresident usPresident = new USPresident(56); try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/home/nikhil/dev/USPresident.data"))){ oos.writeObject(usPresident); usPresident.setTerm(57); oos.wr
请参阅下面的剪辑

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.
序列化它.
将术语重置为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用作Object签名的标识符,而不是状态.

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

看一下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;
}

为什么这么奇怪的行为?

解决方法

你的书是错误的,而staticVersionUID是静态的,用于处理类本身的不同版本.

序列化的想法是采用一个活动对象(usPresident指向的对象)并将其所有状态保存为一些外部形式(字节,XML,JSON).然后,您可以将该状态恢复为该对象的副本.这就像在文字处理器中保存文件一样.

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读