public static void save(Settings settings) {
try {
ObjectOutputStream os =
new ObjectOutputStream(
new FileOutputStream(settingsFile));
os.writeObject(settings);
os.close();
} catch(Exception e) {
e.printStackTrace();
}
}
这是将类设置保存到文件的代码。
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;
}
此代码将读取文件并返回转换为Settings
的Object错误是获取
Settings settings = (Settings) is.readObject();
并且StackTrace是
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)
我不完全确定为什么我收到此错误,因为写入文件的对象是“设置”,正在读取的对象也是“设置”。任何帮助将不胜感激
答案 0 :(得分:2)
您序列化的类的版本为X
,您使用的当前Settings
类的版本为Y
(其中,版本是每个Serializable
具有的版本UID ,即使你没有定义一个,它也会由Java通过查看你的类内部来生成)
将来在您使用Serializable的类中定义private (no matter, it could be public/protected too) static final long serialVersionUID
时,使用值(例如1L
)将避免此问题。
要修复您的例外,现在定义一个值为serialVersionUID
的{{1}}(因此它们将匹配)并对其进行反序列化。 (并且它不安全。)
无论如何,我只是应该使用新的UID值(1L?)对其进行重新序列化以使其始终兼容,因为如果您不提供此值,则可以鼓励其他人出错。
Serializable
JavaDoc对我的解释比我好。
序列化运行时与每个可序列化的类a关联 版本号,称为serialVersionUID,在此期间使用 反序列化以验证序列化的发送方和接收方 object已加载与该对象兼容的类 尊重序列化。如果接收器已加载了一个类 具有与其不同的serialVersionUID的对象 相应的发件人的类,然后反序列化将导致 InvalidClassException。可序列化的类可以声明它自己的类 serialVersionUID通过声明一个名为的字段显式地显示 "的serialVersionUID"必须是static,final和long类型:
5215625451621355973
如果是 serializable类没有显式声明serialVersionUID, 然后序列化运行时将计算默认值 该类的serialVersionUID值基于该方面的各个方面 class,如Java(TM)对象序列化中所述 规格。但是,强烈建议所有人 可序列化类显式声明serialVersionUID值,因为 默认的serialVersionUID计算对类非常敏感 细节可能因编译器实现而异,并且可以 因此导致意外的InvalidClassExceptions期间 反序列化。因此,要保证一致的serialVersionUID 不同java编译器实现的值,可序列化 class必须声明一个显式的serialVersionUID值。也是 强烈建议显式serialVersionUID声明使用 尽可能使用私有修饰符,因为此类声明仅适用于 立即声明的类 - serialVersionUID字段不是 作为继承成员有用。数组类不能声明显式 serialVersionUID,所以它们总是有默认的计算值,但是 免除匹配serialVersionUID值的要求 数组类。
答案 1 :(得分:0)
检查代码中的serialVersionUID - 这是Serializable类的通用版本标识符。
e.g。 static final long serialVersionUID = 1L;
反序列化使用此数字来确保加载的类与序列化对象完全对应。如果未找到匹配项,则抛出InvalidClassException