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

为什么不在Java中序列化抽象类?,java,oop,serialization,abstract-class,Java,Oop,Serialization,Abstract Class,我已经读到,一般来说,抽象类不应该在Java中序列化。子类应该是可序列化的(如果需要,可以使用定制的读写方法,例如当抽象类有字段时) 这背后的原因是什么?为什么它被认为是糟糕的设计 Update1:我有一个抽象类,包含一些字段和三个子类。到目前为止,我正在使用以下方法 我已经使所有的子类都可以用自定义的读写方法序列化。在抽象类中,我有以下方法 void writeFields(ObjectOutputStream out)throws IOException { .... } void rea

我已经读到,一般来说,抽象类不应该在Java中序列化。子类应该是可序列化的(如果需要,可以使用定制的读写方法,例如当抽象类有字段时)

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

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

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

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

void readFields(ObjectInputStream in) throws IOException, ClassNotFoundException{ ... }
在自定义的读写方法中,我调用这些子类中的方法来(反)序列化抽象类中的字段。这种方法正确吗?还是有其他更好的方法


更新2:我采纳了Tom的建议,使我的抽象类可序列化。(我希望所有的子类都是可序列化的,并且我在抽象类中有数据)这是一个旁白,但为了完成我正在使用的故事,让我们采取一个开放的立场。如果要反序列化对象,其类型是什么


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

我认为原因是,如果抽象类实现了可序列化,就没有办法说子类型不应该是可序列化的。最好让每个具体类型自己声明…

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

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

请注意,
java.io.Serializable
是一种攻击。它不应该是一个接口。注释(或像
transient
这样的语言演变)更合适


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

这是唯一糟糕的设计,因为这是一个强制决定,如果您想要一个具有不可序列化成员的子类,该怎么办

这就是为什么


例如,列表是不可序列化的,但每个主要的列表实现都是可序列化的。(我知道list是一个接口,但是一个没有成员的抽象类=/=一个接口)

+1,本来想说同样的事情,但你的回答比我说的要简洁得多。如果你反序列化对象,它的类将与序列化的对象相同(给予或接受
writeReplace
/
readResolve
)。我相信你的论点是有缺陷的。不可能实例化一个抽象类。因此,你永远不可能需要反序列化一个astract类。抽象类的任何反序列化都将在一个派生的具体类的上下文中进行,这意味着,该类在反序列化时是已知的。@Tom,@dwb,我同意在这些情况下,派生类需要序列化,而不是基类。@Babak Naffas否如果基类包含数据,则确实需要序列化。这个问题适用于任何面向对象的语言。@athena你真的不希望API中有这样的方法。为什么不?我希望所有子类都是可序列化。抽象类有字段。在这种情况下,使抽象类可序列化(使用自定义读写方法)是否更好?@athena我建议使基类可序列化,无论是接受默认的串行形式还是提供另一种形式。添加允许其他类读取和写入字段的方法将是不好的。感谢您指出这些方法可能会导致问题。我希望所有子类都可序列化。抽象类有字段。在这里评估,使抽象类可序列化更好吗?查看集合框架-否;)AbstractList不可序列化。但无论如何,差别并不大。