我有一个继承树,其中Class A implements Serializable{}
Class B extends A{}
和Class C extends B{}
依此类推至class Z extends Y{}
根据序列化:
“自Class A
实现Serializable
以来,所有Z
的子类都变为'Serializable'”。当我们尝试序列化Z
的对象时,所有超类对象都将被序列化。
问题:
当我序列化Class C
的对象时,如何避免Z Class
被序列化的对象?
答案 0 :(得分:1)
是的,如果C在Z的超类链中,并且想要序列化Z,那么C也将被序列化。您可以使用以下技术之一来避免或解决此问题:
重新排列班级层次结构。
也就是说,使C不再是Z的超类。大概你不想这样做,但考虑到不对C进行序列化的目标,可能是合理的。
控制序列化的C字段。
您可以将transient
标记为未序列化的C字段。也许更好的方法是在C中声明一个serialPersistentFields
数组,可能为空,包含要序列化的C字段的名称。与标记您不希望序列化为transient
的字段相比,这可能更容易或更易于维护。请注意,C仍然是序列化的,但可以省略其字段的序列化。
为C。
提供自定义序列化格式即,使用readObject
和writeObject
方法。如果您未从defaultWriteObject
方法调用writeObject
,则不会发生C的自动字段序列化。同样,请勿在{{1}}方法中调用defaultReadObject
。请注意,如上所述,这仍然序列化C本身,但避免序列化其部分或全部字段。
为Z。
提供序列化代理为Z提供readObject
方法。writeReplace
方法排列事物,以便当有人请求序列化Z时,不同的对象(例如,称为ZProxy)被序列化代替。让您的writeReplace
方法构造一个ZProxy实例,该实例包含您想要序列化的Z的数据,并返回该ZProxy实例。该实例将被序列化以代替Z实例。 ZProxy不必与Z在同一个类层次结构中;它可以完全不相关。反序列化ZProxy实例时,请确保ZProxy具有writeReplace
方法,该方法从ZProxy中的数据构造Z实例并返回Z实例。
有关序列化代理的详细信息,请参阅Bloch, Effective Java ,第78项。
您可能还希望提供一个抛出异常的Z.readObject方法,以防止某人伪造一个声称包含Z的序列化实例然后反序列化的序列化字节流。这将强制执行约束,即只有ZProxy实例出现在序列化字节流中,而不是实际的Z实例。