Java 序列化 - java.io.InvalidClassException 本地类不兼容 [英] Java serialization - java.io.InvalidClassException local class incompatible

查看:24
本文介绍了Java 序列化 - java.io.InvalidClassException 本地类不兼容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个公共类,它实现了 Serializable,它由多个其他类扩展.之前只有那些子类被序列化 - 从来没有超类.

I've got a public class, which implements Serializable, that is extended by multiple other classes. Only those subclasses were ever serialized before - never the super class.

超类定义了一个serialVersionUID.

The super class had defined a serialVersionUID.

我不确定它是否重要,但它没有被标记为私有,而是它只是具有默认保护 - 您可能会说它是包保护的

I'm not sure if it matters, but it was not marked private, but rather it just had the default protection - you might say it was package protected

static final long serialVersionUID = -7588980448693010399L;

无论是超类还是任何子类,都实现了 readObject 或 writeObject,并且没有一个子类具有明确定义的 serialVersionUID.我认为在超类中定义一个就足够了.

The super class, nor any of the subclasses, however implemented readObject or writeObject, and none of the subclasses had an explicitly defined serialVersionUID. I figured one defined in the superclass would be sufficient.

尽管如此,只要读回先前序列化的对象,直到一个新的实例变量,一个 List/ArrayList,连同一个新方法被添加到超类,并且一些私有实例变量被添加到一个其子类.

Despite all this, things were fine as far as reading back previously serialized objects until a new instance variable, a List/ArrayList, along with a new method was added to the super class, and some private instance variables were added to one of its subclasses.

现在,当尝试读回先前序列化的对象时,会引发异常.一个类似的:

Now when trying to read back previously serialized objects, an exception is being thrown. One similar to this:

com.SomeCompany.SomeSubClass; local class incompatible: stream classdesc serialVersionUID = 1597316331807173261, local class serialVersionUID = -3344057582987646196

我假设这是因为默认的serialVersionUID(因为我没有在任何子类中声明而使用)现在由于超类和一个子类的变化而发生了变化.

I'm assuming this is caused because the default serialVersionUID, which was used because I didn't declare one in any of the subclasses, has now changed due to the changes in the superclass and one subclass.

关于如何摆脱这种困境的建议将不胜感激.我假设我需要实现 readObject 和 writeObject,但除了调用 defaultReadObject() 和 defaultWriteObject() 之外,我不确定我需要做什么.我也不知道是否需要向所有子类添加 serialVerisonUID,或者每个子类是否需要实现 readObject 和 writeObject,或者我是否可以只实现一次,假设我需要在超类中实现.

Suggestions on how to get out of this dilemma would be appreciated. I'm assuming I need to implement readObject and writeObject, but other than invoking defaultReadObject() and defaultWriteObject(), I'm not exactly sure what I need to do. Nor do I know if I need to add serialVerisonUIDs to all of the subclasses or if readObject and writeObject need to be implemented by each subclass, or if I can just implement them once, assuming I need to at all, in the superclass.

推荐答案

@DanielChapman 对 serialVersionUID 给出了很好的解释,但没有解决方案.解决方案是:运行 serialver 程序在你所有的类上.将这些 serialVersionUID 值放入您的当前 版本的类中.只要当前的类与旧版本串行兼容,你应该没问题.(未来代码的注意事项:你应该总是所有Serializable类上有一个serialVersionUID)

@DanielChapman gives a good explanation of serialVersionUID, but no solution. the solution is this: run the serialver program on all your old classes. put these serialVersionUID values in your current versions of the classes. as long as the current classes are serial compatible with the old versions, you should be fine. (note for future code: you should always have a serialVersionUID on all Serializable classes)

如果新版本串行兼容,那么您需要使用自定义的readObject 实现(您只需要一个自定义的writeObject(如果您尝试编写与旧代码兼容的类数据).一般来说,添加或删除类字段不会使类串行不兼容.更改现有字段的类型通常会.

if the new versions are not serial compatible, then you need to do some magic with a custom readObject implementation (you would only need a custom writeObject if you were trying to write new class data which would be compatible with old code). generally speaking adding or removing class fields does not make a class serial incompatible. changing the type of existing fields usually will.

当然,即使新类串行兼容,您可能仍然需要自定义的readObject 实现.如果您想填充从旧版本类保存的数据中缺少的任何新字段,您可能需要这个(例如,您有一个新的列表字段,您希望在加载旧类数据时将其初始化为空列表).

Of course, even if the new class is serial compatible, you may still want a custom readObject implementation. you may want this if you want to fill in any new fields which are missing from data saved from old versions of the class (e.g. you have a new List field which you want to initialize to an empty list when loading old class data).

这篇关于Java 序列化 - java.io.InvalidClassException 本地类不兼容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆