【问题标题】:What is are the characteristics of EnumSets regarding class versioning?EnumSet 在类版本控制方面的特点是什么?
【发布时间】:2018-02-09 12:39:51
【问题描述】:

javadoc 和这个question 都强调

枚举集在内部表示为位向量。

现在我想知道 - 当通过线路将(标准 Java 序列化)EnumSet 对象发送到一些 其他 JVM 时,可能有不同版本的底层枚举类?

换句话说:当我发送一些Set<MyEnum> 时,很有可能在 other JVM 上的反序列化期间抛出异常(如果 my JVM 正在使用 other JVM 不知道的一些MyEnum.NEW_GUY)。在这种情况下,反序列化会尝试实例化 other JVM 上的类中不存在的枚举常量。

但假设 EnumSet 不传输枚举常量实例(但只是设置了一些位为真,一些位为假) - 当序列化 EnumSet 包含 MyEnum.NEW_GUY 时会发生什么?

我试图确定一个规范来告诉我应该发生什么(而不是假设这是一个实现细节),但到目前为止还没有运气。

【问题讨论】:

  • “但假设 EnumSet 不传输枚举常量实例” 查看源码(JDK9),情况并非如此。它使用一个序列化代理来保存元素类型Class 和一个常量数组。
  • 根据源码:从流中读取对象后重新计算位向量。序列化仅将枚举值的数组写入流(除了枚举类)。这意味着您可以更改枚举值的顺序,也可以添加新的枚举值,只要您没有在集合中序列化它们。

标签: java enums


【解决方案1】:

仅关于实现(使用 Oracle Java 8),答案是:它不“只是”一个位集。

含义:可以快速编写一个将 EnumSet 实例序列化到文件中的测试,然后更改枚举类,并运行从文件中读回集合的代码。

结果:

  • 如果文件包含不再存在的枚举常量,则会抛出 java.io.InvalidObjectException: enum constant B does not exist in class com.ibm.hwmca.z.managed.TestEnum
  • 如果所有枚举常量都存在,但它们的顺序发生了变化 - 被读回的集合仍然是正确的。

换句话说:该测试表明,序列化的 EnumSet 确实包含“更多”信息,而不仅仅是一个普通的位集。该实现能够 A) 检测“丢失的”枚举常量和 B) 处理仅影响条目排序的枚举类的更改。与@Seelenvirtuose 的 cmets 匹配,序列化 EnumSet 不是位向量,而是包含实际枚举常量的数组(因此对于完全相同的版本冲突开放)。

仍在搜索观察到的行为是否有规范

【讨论】:

    猜你喜欢
    • 2019-05-22
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 2014-04-03
    • 1970-01-01
    • 2018-02-18
    • 2017-02-20
    相关资源
    最近更新 更多