1

我一直在互联网(包括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...就是 我无法弄清楚的 1 来自哪里。serialVersionUIDReportList

我的工作理论是这样的:Serializable在 ReportList 中实施之前,我有一个等于 的 UID 1L,所以我假设这就是 1 的来源(对吗?请确认或否认?)

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

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

4

2 回答 2

2

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

您的选择是:

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

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

private static final long serialVersionUID = 1L;

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

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

将定义更改为 1,重新编译 JAR,它应该可以运行。

于 2013-06-19T16:03:49.500 回答