我经常听到人们说序列化破坏了封装,并且通过提供自定义序列化可以在一定程度上最大限度地减少这种封装损失。有人能提供一个具体的例子来证明由于默认序列化而导致的封装丢失,以及如何通过自定义序列化来最大限度地减少这种损失?
我将此问题标记为与Java相关,但答案可能与语言无关,因为我认为这是跨平台和语言的常见问题。
答案 0 :(得分:2)
很棒的问题!首先,让我们得到封装的定义并从那里开始。 This wikipedia article以下列方式定义封装:
序列化,至少就像Java那样,对这两个概念产生了影响。在Java中实现Serializable
接口时,实质上是告诉JVM所有非transient
成员变量及其声明顺序定义了可以从中重构对象的契约。一个字节流。当且仅当您的所有成员变量的类定义也实现Serializable
时,这将递归地工作,这是您可能遇到麻烦的地方。
封装问题
基于先前的封装定义,特别是第一项,封装使您无法了解您正在处理的对象实际上是如何在其成员变量下工作的。正确地实现Serializable
“会迫使您作为开发人员更多地了解您正在处理的对象,而不是您在功能意义上可能关心的对象。从这个意义上说,实施Serializable
直接反对封装。
自定义序列化
在每种情况下,序列化都需要了解哪些数据构成特定类型的“对象”。 Java的Serializable
接口通过强制您了解希望序列化的每个transient
的每个成员变量的Object
状态,从而将其发挥到极致。您可以通过定义需要序列化的类型外部的序列化机制来解决这个问题,但是会有设计权衡 - 例如您可能需要在它们实现的接口级别处理Objects而不是直接与其成员变量交互,并且您可能会失去从序列化字节流重建精确Object类型的能力。 / p>
答案 1 :(得分:0)
Java默认序列化以字段方式逐字写入和读取,因为它暴露了对象的内部结构,从而破坏了封装。如果更改类的内部结构,则可能无法正确还原对象状态。使用自定义序列化时,如果更改了类,则可以尝试更改readObject,以便可以正确恢复保存的对象。