2013-04-26 56 views
13

當我讀到的關於Thinking in javaSerializable接口,有一句話,說:爲什麼在寫入ObjectOutputStream時必須首先調用defaultWriteObject函數?

如果使用默認的機制來寫你的對象的非暫時性的部分,你必須調用defaultWriteObject()作爲writeObject()中的第一個操作,以及readObject()中的第一個操作的defaultReadObject()。

而且在docs.oracle.com 5.6.2

添加的writeObject /方法readObject - 如果版本讀取流具有這些方法,然後調用readObject預計,像往常一樣,讀取由寫入流所需的數據默認序列化。它應該在讀取任何可選數據之前先調用defaultReadObject。 writeObject方法與往常一樣,可以調用defaultWriteObject來寫入所需的數據,然後寫入可選數據。

因此,如果我不先致電defaultWriteObject,並且如果在該調用之前我寫了其他東西,會不會有任何問題?我已經嘗試過了,但它似乎仍然在我的例子中運行良好。所以如果有什麼問題,在什麼情況下會發生?

+0

它是如此,因爲它是如此。除非你在這裏得到了一位原創設計師,這不太可能,否則你得到的任何東西都會或多或少的不知道猜測。不建設性。 – EJP 2013-04-27 10:49:26

回答

4

的Java對象序列化規範是關於這個主題含糊:寫將由需要的任何可選的數據之前

要麼ObjectOutputStreamdefaultWriteObjectwriteFields方法必須被調用一次(也是唯一的一次)對應的readObject方法恢復對象的狀態;即使沒有寫入可選數據,defaultWriteObjectwriteFields仍必須調用一次。如果defaultWriteObjectwriteFields在寫入可選數據(如果有)之前未被調用一次,則在ObjectInputStream無法解析定義該方法的類時,實例反序列化的行爲爲undefined

下面是一個old thread,它給出了一個可能發生問題的例子。

下面是另一個例子的JBoss AS Jira ticket

+0

我最近遇到了這個問題,並且它在接收器中造成了StreamCorruptedException的棘手問題,所以我強烈建議您始終調用defaultRead/WriteObject,即使您的類的所有成員都是瞬態的。 – 2013-04-26 16:24:27

1

我認爲文檔中的關鍵詞是「應該」,這意味着你不必這樣做。

我認爲這比其他任何事情都更好。如果我第一次閱讀你的代碼,並看到你在第一行中默認了讀/寫,我可以對自己說「好吧,完成90%的課程」,並專注於你的自定義代碼,它負責所有非瞬態,非靜態實例變量。

最重要的是以相同的順序讀取/寫入。除此之外,你可以隨心所欲地做。

0

我認爲這是因爲你知道你在兩邊做了什麼,並做了「相同」或更好的相反......但是,如果其他程序員會在不知道您不使用默認設置的情況下針對您的序列化編寫反序列化,那麼他可能會使用使用推薦的defaultReadObject,然後運行到奇怪的異常。

0

它在有效的Java定律描述:

如果所有實例字段是暫時的,它在技術上是允許與調用defaultWriteObject和defaultReadObject分配,但不建議這樣做。即使所有實例字段都是瞬態的,調用defaultWriteObject也會影響序列化表單,從而大大增強了靈活性。生成的序列化表單可以在以後的版本中添加非瞬時實例字段,同時保持向前和向後的兼容性。如果實例在更高版本中序列化並在早期版本中反序列化,則添加的字段將被忽略。如果早期版本的readObject方法未能調用defaultReadObject,則反序列化將失敗,並出現StreamCorruptedException。

相關問題