从文件读取会导致序列化版本UID错误



我一直在互联网上搜索(包括stackoverflow(以获取此错误的解释,但尚未遇到答案(或至少一个我可以理解的答案(。

我正在尝试序列化一个类,以便我可以将对象保存到文件中。 第一步是读取文件的当前内容,以便我可以在其中添加新对象。 为此,我使用以下代码:

//masterFilePath is a java.io.File that contains the "master file" I'm reading.
//ReportList is a simple extension of ArrayList
String[][] returner = null; 
ReportList listOfReports = null;
try{
    FileInputStream fileReader = new FileInputStream(masterFilePath);
    ObjectInputStream objectReader = new ObjectInputStream(fileReader);
    listOfReports = (ReportList) (objectReader.readObject()); //Problem Line
    objectReader.close();
} catch (IOException | ClassNotFoundException e){
    e.printStackTrace();
}

当它到达标记为//Problem Line的行时,它会抛出此错误:

com.Private.automatorContainers.ReportList; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 8996775622132817386

我知道8996...是我目前拥有的serialVersionUID ReportList我无法弄清楚的是 1 的来源。

我的工作理论是这样的:在我在 ReportList 中实现 Serializable 之前,我有一个等于 1L 的 UID,所以我假设这就是 1 的来源(对吧? 请确认还是拒绝?

我有两个问题。 首先,UID 存储在哪里?我不知道这样的东西存储在.java文件之外? 我认为其他一切都是在编译时完成的。 显然,我的理解存在漏洞。

其次,如何让我的程序意识到 1 是错误的serialVersionUID并且需要更新?

这里的根本问题是文件系统上该文件的内容是使用与正在运行的代码使用的版本不兼容的ReportList版本编写的。Java 通过在将对象类写入流时记录对象的类的 serialVersionUID 来检测这种不兼容性;稍后,当您从流中读回该对象时,Java 会将记录的 serialVersionUID 与它在运行时为对象的类找到的 serialVersionUID 进行比较。

您的选择是:

    使用
  • 最新版本的正在运行的代码重新创建该内容,使用最初用于生成内容的任何进程。
  • 修改正在运行的代码,使其与最初编写文件的版本兼容,方法是将运行代码中 ReportList 类的serialVersionUID设置为1L以匹配文件中的内容,正如此线程中的其他人所建议的那样。请注意,仅当您确定文件中对象的字段与最新代码中的字段相同,或者已重写默认对象序列化行为时,才能执行此操作。

如果流声明序列化对象具有serialVersionUID = 1,则读取它的唯一方法是将类 serialVersionUID 也设置为 1。

private static final long serialVersionUID = 1L;

如果您没有定义serialVersionUID Java 将根据类的属性为您生成一个,这很可能不是 1。

当您将对象写入文件时,似乎 serialVersionUid 在类定义中为 1。

将定义更改为 1,重新编译 JAR,它应该可以正常工作。

最新更新