我有一个继承树,其中
A 类实现 Serializable{}
B 类扩展 A{}
和 C 类扩展 B{}
等等直到 Z 类扩展 Y{}
根据序列化:
“由于 A 类
实现了 Serializable
,所有直到 Z
的子类都变成了‘Serializable’”。当我们尝试序列化 Z
的对象时,所有父类(super class)对象都将被序列化。
问题:
当我序列化Z类
的对象时,如何避免C类
的对象被序列化?
最佳答案
对,如果 C 在 Z 的父类(super class)链中,而你想序列化 Z,那么 C 也会被序列化。您可以使用以下技术之一避免或解决此问题:
重新排列类层次结构。
也就是说,使 C 不再是 Z 的父类(super class)。大概您不想这样做,但考虑到不序列化 C 的目标,考虑这一点可能是合理的。
控制被序列化的C的字段。
您可以将未序列化的 C 字段标记为 transient
。也许更好的方法是在 C 中声明一个 serialPersistentFields
数组,它可能为空,包含要序列化的 C 字段的名称。这可能比将您不想序列化的字段标记为 transient
更容易或更易于维护。注意C仍然是序列化的,但是可以省略其字段的序列化。
为 C 提供自定义序列化格式。
即使用readObject
和writeObject
方法。如果您不从 writeObject
方法中调用 defaultWriteObject
,那么 C 的自动字段序列化都不会发生。同样,不要从 readObject
方法中调用 defaultReadObject
。请注意,如上所述,这仍然会序列化 C 本身,但会避免序列化其部分或全部字段。
为 Z 提供序列化代理。
为 Z 提供一个 writeReplace
方法。writeReplace
方法安排事情以便当有人请求序列化 Z 时,一个不同的对象(称为例如 ZProxy)被序列化。让您的 writeReplace
方法构造一个 ZProxy 实例,其中恰好包含您要序列化的 Z 中的数据,并返回该 ZProxy 实例。该实例将被序列化以代替 Z 实例。 ZProxy 不必与 Z 在同一类层次结构中;它可以完全无关。当 ZProxy 实例被反序列化时,确保 ZProxy 有一个 readResolve
方法,该方法从 ZProxy 中的数据构造一个 Z 实例并返回 Z 实例。
有关序列化代理的更多信息,请参阅 Bloch,Effective Java,第 78 项。
您可能还想提供一个抛出异常的 Z.readObject 方法,以防止有人伪造一个声称包含 Z 的序列化实例的序列化字节流,然后将其反序列化。这强制了只有 ZProxy 实例出现在序列化字节流中的约束,而不是实际的 Z 实例。
关于java - 停止java中继承树中某些类类型的序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20457951/