尝试保存和读取文件时获取java.io.InvalidClassException

尝试保存和读取文件时获取java.io.InvalidClassException,java,serialization,io,Java,Serialization,Io,这是将类设置保存到文件的代码 public static void save(Settings settings) { try { ObjectOutputStream os = new ObjectOutputStream( new FileOutputStream(settingsFile)); os.writeObject(settings); os.c

这是将类设置保存到文件的代码

public static void save(Settings settings) {
    try {
        ObjectOutputStream os = 
                new ObjectOutputStream(
                        new FileOutputStream(settingsFile));
        os.writeObject(settings);
        os.close();
    } catch(Exception e) {
        e.printStackTrace();
    }
}
此代码将读取该文件并返回被强制转换为设置的对象

错误是get位于

public static Settings load() {
    try {
        ObjectInputStream is = 
                new ObjectInputStream(
                        new FileInputStream(settingsFile));
        Settings settings = (Settings) is.readObject();
        is.close();
        return settings;
    } catch(Exception e) {
        e.printStackTrace();
    }
    return null;
}
而StackTrace是

Settings settings = (Settings) is.readObject();    

我不完全清楚为什么会出现这个错误,因为写入文件的对象是设置,而正在读取的对象也是设置。任何帮助都将不胜感激

您序列化的类的版本为
X
,当前使用的
设置
类的版本为
Y
(其中versions是每个
Serializable
拥有的版本UID,即使您没有定义一个,它也会通过查看类内部来由Java生成)

将来,在使可序列化的类中定义一个
私有(不管它是否也是公共的/受保护的)静态最终长serialVersionUID
,并使用一个值(例如
1L
)将避免此问题

要立即修复异常,请定义一个值为52156251621355973的
serialVersionUID
(因此它们将匹配)并反序列化它(这是不安全的)

无论如何,我应该用新的UID值(1L?)重新序列化它,使其始终兼容,因为如果不提供此值,可能会鼓励其他人出错

JavaDoc比我解释得更好

序列化运行时与每个可序列化类关联 版本号,称为serialVersionUID,在 反序列化以验证序列化的发送方和接收方 对象已为该对象加载与兼容的类 关于序列化。如果接收器已为 对象的SerialVersionId与的SerialVersionId不同 对应发件人的类,则反序列化将导致 InvalidClassException。可序列化类可以声明自己的类 通过声明名为 “serialVersionUID”必须是静态的、最终的且类型为long:

java.io.InvalidClassException: com.Settings; local class incompatible: stream classdesc serialVersionUID = 5215625451621355973, local class serialVersionUID = -6263468811172060812
at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.Settings.load(Settings.java:51)
at com.Main.main(Main.java:23)
如果 serializable类未显式声明serialVersionUID, 然后序列化运行时将计算默认值 该类的SerialVersionId值基于 类,如Java(TM)对象序列化中所述 但是,强烈建议所有 可序列化类显式声明serialVersionUID值,因为 默认的serialVersionUID计算对类高度敏感 详细信息可能因编译器实现而异,可以 因此,在运行期间会导致意外的InvalidClassException 因此,为了保证一致的serialVersionUID 跨不同java编译器实现的值,可序列化 类必须声明显式的serialVersionUID值。它也是 强烈建议显式serialVersionUID声明使用 私有修饰符,因为此类声明仅适用于 立即声明的类--SerialVersionId字段不可用 用作继承成员。数组类不能声明显式 serialVersionUID,因此它们始终具有默认的计算值,但 对于以下情况,不需要匹配serialVersionUID值 数组类


检查代码中的serialVersionUID-它是可序列化类的通用版本标识符

e、 g.
static final long serialVersionId=1L;


反序列化使用此数字来确保加载的类与序列化对象完全对应。如果找不到匹配项,则会引发InvalidClassException

能否显示
设置的定义
?自上次序列化对象以来,您是否更改了类定义?哇,我觉得很傻。我在Se中编辑了一些内容ttings类在我序列化它之后,对你来说,我认为这是把它搞砸了。我刚刚重新序列化了文件,它工作得很好。如果你把它作为一个答案,我会标记它已解决。谢谢你的帮助!我现在明白了。这是我第一次尝试使用Serializable。谢谢!没问题:)如果你的问题已解决,考虑接受我的回答(或者任何其他帮助你的答案)
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;