如何确保Java序列化中枚举的一致性?

16

当我序列化一个对象时,可以在类级别使用 serialVersionUID 机制来确保两种类型的兼容性。

但是,当我序列化枚举值的字段时会发生什么?有没有一种方法可以确保在序列化和反序列化之间枚举类型没有被篡改?

假设我有一个枚举类型 OperationResult {SUCCESS, FAIL},以及一个正在被序列化的对象中名为 "result" 的字段。在对象反序列化时,如何确保 "result" 仍然正确,即使有人恶意地将这两个值反转?(假设该枚举在其他位置被声明为静态枚举)

出于好奇,我想知道 - 我使用 jar 级别的身份验证来防止篡改。

2个回答

22

从:http://www.theserverside.com/news/thread.tss?thread_id=50190#265205

枚举特性的设计者认为,在运行时创建新的枚举对象并没有实用价值。他们非常小心地不允许这样做。

因此,看起来枚举对象不能完整地进行序列化和反序列化。此外,根据http://java.sun.com/javase/6/docs/platform/serialization/spec/serial-arch.html#6469

枚举常量与普通可序列化或可外部化对象的序列化方式不同。枚举常量的序列化形式仅由其名称组成;常量的字段值不在形式中。为了序列化一个枚举常量,ObjectOutputStream 写入枚举常量的 name 方法返回的值。要反序列化枚举常量,ObjectInputStream 从流中读取常量名称;然后通过调用 java.lang.Enum.valueOf 方法获取枚举类型的常量,传递接收到的常量名称作为参数。与其他可序列化或可外部化对象一样,枚举常量可以作为后续出现在序列化流中的反向引用的目标。

枚举常量序列化的过程不能自定义:枚举类型定义的任何类特定的 writeObject、readObject、readObjectNoData、writeReplace 和 readResolve 方法在序列化和反序列化期间都将被忽略。同样,所有枚举类型的 serialPersistentFields 或 serialVersionUID 字段声明也都将被忽略——所有枚举类型都有一个固定的 serialVersionUID,为0L。对枚举类型的可序列化字段和数据进行文档记录是不必要的,因为发送的数据类型没有变化。


5

在反序列化期间,枚举会被读取和替换。引用版本1.5的序列化发行说明

序列化枚举实例的规则与序列化“普通”可序列化对象的规则不同:枚举实例的序列化形式仅包含其枚举常量名称以及标识其基本枚举类型的信息。反序列化行为也有所不同——使用类信息查找适当的枚举类,并使用该类和接收到的常量名称调用Enum.valueOf方法以获取要返回的枚举常量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接