2010-12-15 19 views
6

我讀過一般抽象類不應該在Java中進行Serializable。子類應該是可序列化的(如果需要,可以使用自定義讀取,寫入方法,例如抽象類具有字段時)。爲什麼不在Java中序列化抽象類?

這是什麼原因?爲什麼它被認爲是不好的設計?

Update1:​​我有一個抽象類,有一些字段和三個子類。截至目前,我正在使用以下方法。

我已經使所有的子類與自定義讀取,寫入方法序列化。在抽象類中,我有以下方法。

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

void readFields(ObjectInputStream in) throws IOException, ClassNotFoundException{ ... } 

在自定義讀取中,在子類中寫入方法我調用這些方法來(抽象)序列化抽象類中的字段。這種方法是否正確?或者有更好的方法嗎?

更新2:我採取了湯姆的建議,並使我的抽象類Serializable。 (我希望所有的子類都是可序列化的,並且我有抽象類中的數據)這是一個旁白,但僅僅是爲了完成我正在使用的故事reflection to change final fields as advised by Jeremy Manson.

+0

這個問題適用於任何面向對象的語言。 – 2010-12-15 17:34:10

回答

1

我不知道它是一定不好的設計。序列化實際上是一個實現問題(請注意,Josh Bloch不同意我的觀點),所以對於接口來說沒有意義。如果抽象類具有狀態,那麼你會想讓它可串行化。如果它沒有國家,那麼沒有任何理由這樣做。

舉個例子吧。 java.security.cert.Certificate是一個抽象的serialisable類,帶有一個"type"可序列化的字段。如果它不是可序列化的,那麼子類就不可能被序列化並設置該字段。你將被迫進行黑客攻擊。

請注意java.io.Serializable是一個黑客。它不應該是一個接口。一個註釋(或者像transient這樣的語言演變)本來會更合適。

與往常一樣,最好是將組合選擇爲繼承,而不是使隨機類可串行化。

+0

請參閱最新的問題。 – athena 2010-12-15 17:49:59

+0

@athena你真的不希望在API中使用這種方法。 – 2010-12-15 19:41:53

+0

爲什麼不呢?我希望所有的子類都是可序列化的。抽象類有字段。在這種情況下,創建抽象類Serializable(使用自定義讀寫方法)會更好嗎? – athena 2010-12-16 07:57:49

3

讓我們採取相反的立場。如果您要對對象進行反序列化,那麼它的類型是什麼?

根據定義,抽象類不能被實例化。如果你可以序列化它,這意味着它也可以被反序列化,並且會爲你提供一個抽象類的實例。這與抽象類的定義相矛盾,因此無法完成。

+0

+1,即將說同樣的事情有點不同,但你的回答說明它比我所說的要簡潔得多。 – 2010-12-15 17:32:45

+3

如果你反序列化了這個對象,它的類將和被序列化的對象一樣(給或者帶'writeReplace' /'readResolve')。 – 2010-12-15 17:39:29

+1

我相信你的論點是有缺陷的。實例化一個抽象類是不可能的。因此,你不可能需要反序列化一個astract類。抽象類的任何反序列化都將放在派生的具體類的上下文中,這意味着該類在反序列化的時候是已知的。 – DwB 2010-12-15 17:41:42

5

我認爲原因是如果一個Abstract類實現了Serializable,那麼就沒有辦法說子類型不應該是Serializable。更好地讓每一個具體類型聲明自己...

+0

+1。集合API就是一個很好的例子。 – Bozho 2010-12-15 17:39:21

+0

我希望所有的子類都是可序列化的。抽象類有字段。在這種情況下,使抽象類Serializable更好嗎? – athena 2010-12-16 07:56:48

+0

看着集合框架 - no;)AbstractList是不可序列化的。但無論如何,這並沒有太大的區別。 – Bozho 2010-12-16 08:06:40

0

這只是不好的設計,因爲它是一個強制決定,如果你想要一個擁有不可序列化成員的子類,該怎麼辦?

這就是爲什麼。

E.g.列表不是可序列化的,但是每個主要列表實現都是。(我知道列表是一個接口,但抽象類沒有成員=/=一個接口)