为什么不在Java中序列化抽象类?

ath*_*ena 7 java oop serialization abstract-class

我已经读过,通常抽象类不应该在Java中使用Serializable.子类应该是可序列化的(如果需要,可以使用自定义读取,写入方法,例如,当抽象类具有字段时).

这背后的原因是什么?为什么它被认为是糟糕的设计?

Update1:我有一个抽象类,包含一些字段和三个子类.截至目前,我正在使用以下方法.

我已经使用自定义读取,写入方法使所有子类可序列化.在抽象类中,我有以下方法.

void writeFields(ObjectOutputStream out)throws IOException { .... }

void readFields(ObjectInputStream in) throws IOException, ClassNotFoundException{ ... }
Run Code Online (Sandbox Code Playgroud)

在自定义读取,子类中的write方法中,我将这些方法称为(de)序列化抽象类中的字段.这种方法是否正确?或者有更好的方法吗?

更新2:我接受了汤姆的建议并制作了我的抽象类Serializable.(我希望所有子类都是Serializable,我在抽象类中有数据)这是一个旁边,但只是为了完成故事,我正在使用反射来改变Jeremy Manson建议的最终字段.

rom*_*afe 8

我认为原因是如果一个Abstract类实现了Serializable,那么就没有办法说子类型不应该是Serializable.最好让每个具体类型为自己声明......


Tom*_*ine 6

我不知道这一定是糟糕的设计。序列化实际上是一个实现问题(注意,Josh Bloch 不同意我的观点),因此对接口没有意义。如果抽象类具有状态,那么您可能希望使其可序列化。如果它没有状态,就没有任何理由让它如此。

让我们举个例子。java.security.cert.Certificate是一个抽象的可序列化类,带有一个可"type"序列化的字段。如果它不可序列化,子类就不可能可序列化并设置该字段。您将被迫进行黑客攻击。

请注意,这java.io.Serializable是一个黑客。它不应该是一个接口。注释(或类似的语言演变transient)会更合适。

与往常一样,最好选择组合而不是继承,而不是使随机类可序列化。


Bab*_*fas 5

让我们采取相反的立场。如果要对对象进行反序列化,它的类型是什么?

根据定义,抽象类不能被实例化。如果您可以序列化它,则意味着它也可以反序列化,这将为您提供抽象类的实例。这与抽象类的定义相矛盾,因此无法做到。

  • 如果您反序列化对象,它的类将与序列化的对象相同(给予或接受 `writeReplace`/`readResolve`)。 (3认同)
  • 我相信你的论点是有缺陷的。不可能实例化抽象类。因此,您永远不可能需要对抽象类进行反序列化。抽象类的任何反序列化都将在派生的具体类的上下文中进行,这意味着该类在反序列化时是已知的。 (2认同)