這篇文章很直接,簡(jiǎn)單易懂。嘗試著翻譯一下 ,原文是What are writeObject and readObject? Customizing the serialization process.
在Java中使用Serialization相當(dāng)簡(jiǎn)單。如果你有一些對(duì)象想要進(jìn)行序列化,你只需實(shí)現(xiàn)Serializable接口。然后,你可以使用ObjectOutputStream將該對(duì)象保存至文件或發(fā)送到其他主機(jī)。所有的non-transient和non-static字段都將被序列化,并且由反序列化重構(gòu)造出一模一樣的對(duì)象聯(lián)系圖(譬如許多引用都指向該對(duì)象)。但有時(shí)你可能想實(shí)現(xiàn)你自己的對(duì)象序列化和反序列化。那么你可以在某些特定情形下得到更多的控制。來(lái)看下面的簡(jiǎn)單例子。
以下是序列化上述class到文件和其反序列化的主函數(shù)。
類SessionDTO展現(xiàn)的是要在兩個(gè)服務(wù)器之間傳輸?shù)膕ession。它包含了一些信息在字段data上,該字段需要被序列化。但是它還有另外一個(gè)字段activationTime,該字段應(yīng)該是session對(duì)象第一次出現(xiàn)在任意服務(wù)器上的時(shí)間。它不在我們想要傳輸?shù)男畔⒅小_@個(gè)字段應(yīng)該在反序列化之后在賦值。進(jìn)一步來(lái)說(shuō),沒(méi)必要把它放在stream中在服務(wù)器中傳遞,因?yàn)樗紦?jù)了不必要的空間。 解決這種情況可以使用writeObject和readObject。有可能你們有一些人沒(méi)有聽(tīng)說(shuō)過(guò)它們,那是因?yàn)樗鼈冊(cè)谠S多Java書(shū)籍中給忽略了,而且它們們也不是眾多流行Java考試的一部分。讓我們用這些方法來(lái)重寫(xiě)SessionDTO:
方法writeObject處理對(duì)象的序列化。如果聲明該方法,它將會(huì)被ObjectOutputStream調(diào)用而不是默認(rèn)的序列化進(jìn)程。如果你是第一次看見(jiàn)它,你會(huì)很驚奇盡管它們被外部類調(diào)用但事實(shí)上這是兩個(gè)private的方法。并且它們既不存在于java.lang.Object,也沒(méi)有在Serializable中聲明。那么ObjectOutputStream如何使用它們的呢?這個(gè)嗎,ObjectOutputStream使用了反射來(lái)尋找是否聲明了這兩個(gè)方法。因?yàn)镺bjectOutputStream使用getPrivateMethod,所以這些方法不得不被聲明為priate以至于供ObjectOutputStream來(lái)使用。 在兩個(gè)方法的開(kāi)始處,你會(huì)發(fā)現(xiàn)調(diào)用了defaultWriteObject()和defaultReadObject()。它們做的是默認(rèn)的序列化進(jìn)程,就像寫(xiě)/讀所有的non-transient和 non-static字段(但他們不會(huì)去做serialVersionUID的檢查).通常說(shuō)來(lái),所有我們想要自己處理的字段都應(yīng)該聲明為transient。這樣的話,defaultWriteObject/defaultReadObject便可以專注于其余字段,而我們則可為這些特定的字段(譯者:指transient)定制序列化。使用那兩個(gè)默認(rèn)的方法并不是強(qiáng)制的,而是給予了處理復(fù)雜應(yīng)用時(shí)更多的靈活性。 你可以從這里或這里讀到更多有關(guān)于序列化的知識(shí)。 自己再補(bǔ)充一些: 1.Write的順序和read的順序需要對(duì)應(yīng),譬如有多個(gè)字段都用wirteInt一一寫(xiě)入流中,那么readInt需要按照順序?qū)⑵滟x值; 2.Externalizable,該接口是繼承于Serializable ,所以實(shí)現(xiàn)序列化有兩種方式。區(qū)別在于Externalizable多聲明了兩個(gè)方法readExternal和writeExternal,子類必須實(shí)現(xiàn)二者。Serializable是內(nèi)建支持的也就是直接implement即可,但Externalizable的實(shí)現(xiàn)類必須提供readExternal和writeExternal實(shí)現(xiàn)。對(duì)于Serializable來(lái)說(shuō),Java自己建立對(duì)象圖和字段進(jìn)行對(duì)象序列化,可能會(huì)占用更多空間。而Externalizable則完全需要程序員自己控制如何寫(xiě)/讀,麻煩但可以有效控制序列化的存儲(chǔ)的內(nèi)容。 3.正如Effectvie Java中提到的,序列化就如同另外一個(gè)構(gòu)造函數(shù),只不過(guò)是有由stream進(jìn)行創(chuàng)建的。如果字段有一些條件限制的,特別是非可變的類定義了可變的字段會(huì)反序列化可能會(huì)有問(wèn)題??梢栽趓eadObject方法中添加條件限制,也可以在readResolve中做。參考56條“保護(hù)性的編寫(xiě)readObject”和“提供一個(gè)readResolve方法”。 4.當(dāng)有非常復(fù)雜的對(duì)象需要提供deep clone時(shí),可以考慮將其聲明為可序列化,不過(guò)缺點(diǎn)也顯而易見(jiàn),性能開(kāi)銷。 |
|