为什么不在 Java 中序列化抽象类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4452941/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why not serialize abstract classes in Java?
提问by athena
I have read that generally abstract classes should not be made Serializable in Java. The subclasses should be serializable (with custom read, write methods if required, for eg. when abstract classes have fields).
我读过一般抽象类不应该在 Java 中被序列化。子类应该是可序列化的(如果需要,可以使用自定义的读取、写入方法,例如,当抽象类具有字段时)。
What is the reason behind this? Why is it considered bad design?
这背后的原因是什么?为什么它被认为是糟糕的设计?
Update1:I have an abstract class with some fields and three subclasses. As of now, I am using the following approach.
Update1:我有一个包含一些字段和三个子类的抽象类。截至目前,我正在使用以下方法。
I have made all the subclasses serializable with custom read, write methods. In the abstract class I have the following methods.
我已经使用自定义读取、写入方法使所有子类都可序列化。在抽象类中,我有以下方法。
void writeFields(ObjectOutputStream out)throws IOException { .... }
void readFields(ObjectInputStream in) throws IOException, ClassNotFoundException{ ... }
In the custom read, write methods in the subclasses I call these methods to (de) serialize the fields in the abstract class. Is this approach correct? Or is there a different better approach?
在自定义的子类中的读、写方法中,我调用这些方法来(去)序列化抽象类中的字段。这种方法是否正确?或者有其他更好的方法吗?
Update 2:I took Tom's advice and made my abstract class Serializable. (I want all subclasses to be Serializable and I have data in the abstract class) This is an aside, but just to complete the story I am using reflection to change final fields as advised by Jeremy Manson.
更新 2:我接受了 Tom 的建议,并将我的抽象类 Serializable。(我希望所有子类都是可序列化的,并且我在抽象类中有数据)这是一个旁白,但只是为了完成这个故事,我按照 Jeremy Manson 的建议使用反射来更改最终字段。
采纳答案by Tom Hawtin - tackline
I don't know that it is necessarily bad design. Serialisation is effectively an implementation issue (note, Josh Bloch disagrees with me), so doesn't make sense for interfaces. If the abstract class has state, then you would want to make it serialisable. If it doesn't have state, there isn't really any reason to make it so.
我不知道这一定是糟糕的设计。序列化实际上是一个实现问题(注意,Josh Bloch 不同意我的观点),因此对接口没有意义。如果抽象类具有状态,那么您可能希望使其可序列化。如果它没有状态,就没有任何理由让它如此。
Let's take an example. java.security.cert.Certificate
is an abstract serialisable class, with a "type"
serialisable field. If it wasn't serialisable it would not be possible for a subclass to be serialisable and set that field. You would be forced in to a hack.
让我们举个例子。java.security.cert.Certificate
是一个抽象的可序列化类,带有一个可"type"
序列化的字段。如果它不可序列化,子类就不可能可序列化并设置该字段。您将被迫进行黑客攻击。
Note that java.io.Serializable
is a hack. It shouldn't have been an interface. An annotation (or language evolution like transient
) would have been more appropriate.
请注意,这java.io.Serializable
是一个黑客。它不应该是一个接口。注释(或类似的语言演变transient
)会更合适。
As always, it's best to prefer composition to inheritance and not to make random class serialisable.
与往常一样,最好选择组合而不是继承,而不是使随机类可序列化。
回答by romacafe
I think the reason is that if an Abstract class implements Serializable, there is no way to say that a sub type should NOT be Serializable. Better to let each concrete type declare for itself...
我认为原因是如果抽象类实现了可序列化,则无法说子类型不应该是可序列化的。最好让每个具体类型为自己声明......
回答by Babak Naffas
Let's take the oposite position. If you were to De-Serialize the object, what would be its type?
让我们采取相反的立场。如果要对对象进行反序列化,它的类型是什么?
By definition, an abstract class can't be instantiated. If you can serialize it, that implies that it can also be deserialized and that would get you an instance of the abstract class. That contradicts the definition of an abstract class and therefore can't be done.
根据定义,抽象类不能被实例化。如果您可以序列化它,则意味着它也可以反序列化,这将为您提供抽象类的实例。这与抽象类的定义相矛盾,因此无法做到。
回答by HaMMeReD
It's only bad design because it's a forced decision, what if you want a subclass that has non-serializable members.
这只是糟糕的设计,因为这是一个被迫的决定,如果您想要一个具有不可序列化成员的子类怎么办。
That's why.
这就是为什么。
E.g. List is not Serializable, but every major list implementation is. (I know list is a Interface, but a abstract class with no members =/= a interface)
例如 List 不是可序列化的,但每个主要的列表实现都是。(我知道 list 是一个接口,但是一个没有成员的抽象类 =/= 一个接口)