oop为什么不在Java中序列化抽象类?
我已经读到,一般来说,抽象类不应该在Java中序列化。子类应该是可序列化的(如果需要,可以使用定制的读写方法,例如当抽象类有字段时)
这背后的原因是什么?为什么它被认为是糟糕的设计
Update1:我有一个抽象类,包含一些字段和三个子类。到目前为止,我正在使用以下方法
我已经使所有的子类都可以用自定义的读写方法序列化。在抽象类中,我有以下方法
void writeFields(ObjectOutputStream out)throws IOException { .... }
void readFields(ObjectInputStream in) throws IOException, ClassNotFoundException{ ... }
在自定义的读写方法中,我调用这些子类中的方法来(反)序列化抽象类中的字段。这种方法正确吗?还是有其他更好的方法
更新2:我采纳了Tom的建议,使我的抽象类可序列化。(我希望所有的子类都是可序列化的,并且抽象类中有数据)这是一个旁白,但为了完成我正在使用的reflection to change final fields as advised by Jeremy Manson.
# 1 楼答案
我不知道这一定是糟糕的设计。序列化实际上是一个实现问题(注意,Josh Bloch不同意我的观点),因此对于接口来说没有意义。如果抽象类具有state,则希望使其可序列化。如果它没有状态,就没有理由这样做
让我们举个例子
java.security.cert.Certificate
是一个抽象的可序列化类,带有"type"
可序列化字段。如果不可序列化,则子类不可能可序列化并设置该字段。你将被迫进行黑客攻击注意
java.io.Serializable
是一种黑客行为。它不应该是一个接口。注释(或者像transient
这样的语言演变)更合适和往常一样,最好选择组合而不是继承,不要使随机类可序列化
# 2 楼答案
让我们看一看oposite的位置。如果要反序列化对象,其类型是什么
根据定义,抽象类不能被实例化。如果您可以序列化它,这意味着它也可以被反序列化,这将为您提供一个抽象类的实例。这与抽象类的定义相矛盾,因此无法实现
# 3 楼答案
我认为原因是,如果抽象类实现了可序列化,那么就没有办法说子类型不应该是可序列化的。最好让每个具体类型自己声明
# 4 楼答案
如果
abstract
类包含重要的for序列化字段,并且您不打算实现自定义对象读写器,那么将该基类声明为Serializable
是必要的将基类(或接口)声明为
Serializable
将使所有子类Serializable
包括任何可传递路径如果您实现了某种框架,后者是有意义的:您可以让用户轻松地自动传播接口,否则您应该记录您仅使用
Serializable
或对用户提供的类执行运行时检查我为实体添加了基类(为了统一命名标准,对于像}值(反序列化时))您不希望这样
id
、createdDate
、updatedDate
这样的字段),但忘记了将其标记为Serializable
。因此,会话存储(Redis)中保存的任何实体都有null
{更新
Serializable
需要公共无参数构造函数进行反序列化。继承声明不会为子类或超类创建任何参数构造函数,这是用户的杂务。没有默认构造函数的超类会中断所有子类的反序列化)更新2有一种方法可以声明子类不是为序列化而设计的,即使它是从
Serialazable
基类继承的,尽管它是运行时功能:# 5 楼答案
这只是一个糟糕的设计,因为这是一个强制的决定,如果您想要一个具有不可序列化成员的子类,该怎么办
这就是为什么
例如,列表是不可序列化的,但每个主要的列表实现都是可序列化的。(我知道list是一个接口,但它是一个没有成员的抽象类=/=接口)