6

我和一位同事讨论了可序列化类的 serialVersionUID:他总是以 a 开头,serialVersionUID = 1L然后在类有一些重大变化时将其加一。

JDK 类似乎总是使用更复杂的、生成的 serialVersionUID,例如在java.lang.String类中:

private static final long serialVersionUID = -6849794470754667710L;

现在我的同事询问这种serialVersionUID 与更简单的serialVersionUID(如1L、2L、3L...)相比的优势?

我们也在 SOF 上进行了搜索,但对给出的答案不是很满意,例如在Why generate long serialVersionUID 而不是简单的 1L?.

在我看来,使用生成的 ID 的优点是它不需要任何关于“旧”类版本的信息。但是当手动增加 ID 时,您必须知道迄今为止的最高值。这可能听起来微不足道(只需查看当前的 serialVersionUID 并将其增加 1),但在更大的软件项目、更大的开发团队或分布式环境中可能会更复杂。

4

2 回答 2

1

使用生成的类的优点是,如果它在没有 a 的情况下逃逸serialVersionUID到野外,它与类的先前版本兼容。

话虽如此,您的同事几乎可以肯定增加它是错误的。serialVersionUID只应在您接受该类已发生不可挽回的更改并且您故意要引入序列化不兼容的情况下进行更改。这种情况在自然界中很少发生,仅限于以不兼容的方式更改类的继承或成员字段的类型的情况。如果你决定上课Serializable,你应该已经接受了一个不会发生这种情况的制度。

于 2016-11-20T10:41:21.763 回答
-1

这是一个有趣的问题,直截了当:我不知道。

SUID 是公共 API 的一部分。一旦你发布了一个在你的控制之外使用的 API,比如 JDK,你就不能在不破坏兼容性的情况下更改这个数字。

所以我看不出使用像 32432544354343L 这样的数字而不是 1L 有什么好处。

但对于内部开发,我看到以 1L 之类的数字开头的一个小优势:

假设我们有 3 个 jars 的 RMI 客户端-服务器应用程序:

  • 客户端.jar
  • 服务器.jar
  • api.jar

在 api.jar 中有一些业务类,如客户端和服务器使用的 Song、Album 等,它们是可序列化的。

现在我们从其中一些类的 1L 的 SUID 开始,在发布后我们更改其中一个类的内部格式,因此我们将 SUID 增加到 2L。

现在客户端和服务器组件都需要包含新的 api.jar。如果我们犯了一个错误并忘记使用新的 api.jar 依赖项更新客户端或服务器,那么在反序列化期间将会出现异常。异常中的消息将包含不兼容的 SUID。

所以这里的数字 1L 和 2L 在消息中。2L > 1L,因此我们知道该组件使用旧的 api.jar。使用 IDE 生成的数字,如 123434534553L 和 654642646363L,我们不知道哪个组件使用旧的 api.jar。

但另一方面,即使是像 LocalDate 这样的新 JDK 类也使用像 123434534553L 这样的数字,而不是更简单的数字。在 apache commons-lang 中似乎有混合,例如 FastDateParser.java 使用简单的 3L。

https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/time/FastDateParser.java

奇怪的...

于 2016-11-20T10:32:42.013 回答