Java網(wǎng)絡(luò)編程精解chapter9_第1頁(yè)
Java網(wǎng)絡(luò)編程精解chapter9_第2頁(yè)
Java網(wǎng)絡(luò)編程精解chapter9_第3頁(yè)
Java網(wǎng)絡(luò)編程精解chapter9_第4頁(yè)
Java網(wǎng)絡(luò)編程精解chapter9_第5頁(yè)
已閱讀5頁(yè),還剩31頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Java網(wǎng)絡(luò)編程精解第9章 對(duì)象的序列化與反序列化參考Java網(wǎng)絡(luò)編程精解的第9章n9.1 JDK類庫(kù)中的序列化APIn9.2 實(shí)現(xiàn)Serializable接口n9.2.1 序列化對(duì)象圖n9.2.2 控制序列化的行為n9.2.3 readResolve()方法在單例類中的運(yùn)用n9.3 實(shí)現(xiàn)Externalizable接口n9.4 可序列化類的不同版本的序列化兼容性第9章 對(duì)象的序列化與反序列化n當(dāng)兩個(gè)Java進(jìn)程進(jìn)行遠(yuǎn)程通信時(shí),一個(gè)進(jìn)程能否把一個(gè)Java對(duì)象發(fā)送給另一個(gè)進(jìn)程呢?答案是肯定的。不過(guò),發(fā)送方需要把這個(gè)Java對(duì)象轉(zhuǎn)換為字節(jié)序列,才能在網(wǎng)絡(luò)上傳送;接收方則需要把字節(jié)序列再恢復(fù)為Jav

2、a對(duì)象。n把Java對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程稱為對(duì)象的序列化;把字節(jié)序列恢復(fù)為Java對(duì)象的過(guò)程稱為對(duì)象的反序列化。第9章 對(duì)象的序列化與反序列化n當(dāng)程序運(yùn)行時(shí),程序所創(chuàng)建的各種對(duì)象都位于內(nèi)存中,當(dāng)程序運(yùn)行結(jié)束,這些對(duì)象就結(jié)束生命周期。n如圖9-1所示,對(duì)象的序列化主要有兩種用途:n(1)把對(duì)象的字節(jié)序列永久的保存到硬盤(pán)上,通常存放在一個(gè)文件中。n(2)在網(wǎng)絡(luò)上傳送對(duì)象的字節(jié)序列。第9章 對(duì)象的序列化與反序列化9.1 JDK類庫(kù)中的序列化APInjava.io.ObjectOutputStream代表對(duì)象輸出流,它的writeObject(Object obj)方法對(duì)參數(shù)指定的obj對(duì)象進(jìn)行序

3、列化,把得到的字節(jié)序列寫(xiě)到一個(gè)目標(biāo)輸出流中。njava.io.ObjectInputStream代表對(duì)象輸入流,它的readObject()方法從一個(gè)源輸入流中讀取字節(jié)序列,再把它們反序列化成一個(gè)對(duì)象,并將其返回。9.1 JDK類庫(kù)中的序列化APIn只有實(shí)現(xiàn)了Serializable或Externalizable接口的類的對(duì)象才能被序列化,否則ObjectOutputStream的writeObject(Object obj)方法會(huì)拋出IOException。n實(shí)現(xiàn)Serializable或Externalizable接口的類也稱為可序列化類。nExternalizable接口繼承自Seria

4、lizable接口,實(shí)現(xiàn)Externalizable接口的類完全由自身來(lái)控制序列化的行為,而僅實(shí)現(xiàn)Serializable接口的類可以采用默認(rèn)的序列化方式。nJDK類庫(kù)中的部分類(如String類、包裝類和Date類等)都實(shí)現(xiàn)了Serializable接口。9.1 JDK類庫(kù)中的序列化API9.1 JDK類庫(kù)中的序列化APIn對(duì)象的序列化主要包括以下步驟。n (1)創(chuàng)建一個(gè)對(duì)象輸出流,它可以包裝一個(gè)其他類型的目標(biāo)輸出流,比如文件輸出流:ObjectOutputStream out=new ObjectOutputStream(new fileOutputStream(D:objectFile.

5、obj);n(2)通過(guò)對(duì)象輸出流的writeObject()方法寫(xiě)對(duì)象:out.writeObject(hello); /寫(xiě)一個(gè)String對(duì)象out.writeObject(new Date(); /寫(xiě)一個(gè)Date對(duì)象9.1 JDK類庫(kù)中的序列化APIn對(duì)象的反序列化主要包括以下步驟。n (1)創(chuàng)建一個(gè)對(duì)象輸入流,它可以包裝一個(gè)其他類型的源輸入流,比如文件輸入流:ObjectInputStream out=new ObjectInputStream(new FileInputStream(D:objectFile.obj);n(2)通過(guò)對(duì)象輸入流的readObject()方法讀取對(duì)象:Str

6、ing obj1=(String)out.readObject(); /讀取一個(gè)String對(duì)象Date obj2=(Date)out.readObject(); /讀取一個(gè)Date對(duì)象n為了能讀出正確的數(shù)據(jù),必須保證向?qū)ο筝敵隽鲗?xiě)對(duì)象的順序與從對(duì)象輸入流讀對(duì)象的順序一致。9.1 JDK類庫(kù)中的序列化APIn例程9-1的ObjectSaver類的main()方法先向objectFile.obj文件寫(xiě)入三個(gè)對(duì)象和一個(gè)int類型的數(shù)據(jù),然后再依次把它們從文件中讀入到內(nèi)存中。1. public static void main(String agrs) throws Exception 2. Obj

7、ectOutputStream out=new ObjectOutputStream(new FileOutputStream(D:objectFile.obj);3. String obj1=hello;4. Date obj2=new Date();5. Customer obj3=new Customer(Tom,20);6. /序列化對(duì)象7. out.writeObject(obj1);8. out.writeObject(obj2);9. out.writeObject(obj3);10. out.writeInt(123); /寫(xiě)入基本類型的數(shù)據(jù)11. out.close(); 9

8、.1 JDK類庫(kù)中的序列化API12./反序列化對(duì)象 13. ObjectInputStream in=new ObjectInputStream(new FileInputStream(D:objectFile.obj);14. String obj11 = (String)in.readObject();15. System.out.println(obj11:+obj11);16. System.out.println(obj11=obj1:+(obj11=obj1);17. Date obj22 = (Date)in.readObject();18. System.out.printl

9、n(obj22:+obj22);19. System.out.println(obj22=obj2:+(obj22=obj2);20. Customer obj33 = (Customer)in.readObject();21. System.out.println(obj33:+obj33);22. System.out.println(obj33=obj3:+(obj33=obj3);23. 24. int var= in.readInt(); /讀取基本類型的數(shù)據(jù)25. System.out.println(var:+var);26. 27. in.close();28. 9.1 JDK

10、類庫(kù)中的序列化APIn例程9-2的SimpleServer服務(wù)器從命令行讀取用戶指定的類名,創(chuàng)建該類的一個(gè)對(duì)象,然后向客戶端兩次發(fā)送這個(gè)對(duì)象。n例程9-3的SimpleClient客戶程序負(fù)責(zé)接收服務(wù)器發(fā)送的對(duì)象。n按照默認(rèn)方式序列化時(shí),如果由一個(gè)ObjectOutputStream對(duì)象多次序列化同一個(gè)對(duì)象,那么由一個(gè)ObjectInputStream對(duì)象反序列化出來(lái)的也是同一個(gè)對(duì)象。9.2 實(shí)現(xiàn)Serializable接口nObjectOuputStream只能對(duì)實(shí)現(xiàn)了Serializable接口的類的對(duì)象進(jìn)行序列化。n默認(rèn)情況下,ObjectOuputStream按照默認(rèn)方式序列化,這種序

11、列化方式僅僅對(duì)對(duì)象的非transient的實(shí)例變量進(jìn)行序列化,而不會(huì)序列化對(duì)象的transient的實(shí)例變量,也不會(huì)序列化靜態(tài)變量。9.2 實(shí)現(xiàn)Serializable接口n例程9-4的Customer1類中,定義了一些靜態(tài)變量、非transient的實(shí)例變量,以及transient的實(shí)例變量。public class Customer1 implements Serializable private static int count; /用于計(jì)算Customer對(duì)象的數(shù)目 private static final int MAX_COUNT=1000; private String name

12、; private transient String password; .9.2 實(shí)現(xiàn)Serializable接口n當(dāng)ObjectInputStream按照默認(rèn)方式反序列化時(shí),有以下特點(diǎn):n如果在內(nèi)存中對(duì)象所屬的類還沒(méi)有被加載,那么會(huì)先加載并初始化這個(gè)類。如果在classpath中不存在相應(yīng)的類文件,那么會(huì)拋出ClassNotFoundException。n在反序列化時(shí)不會(huì)調(diào)用類的任何構(gòu)造方法。n如果一個(gè)實(shí)例變量被transient修飾符修飾,那么默認(rèn)的序列化方式不會(huì)對(duì)它序列化。根據(jù)這一特點(diǎn),可以用transient修飾符來(lái)修飾以下類型的實(shí)例變量:n(1)實(shí)例變量不代表對(duì)象的固有的內(nèi)部數(shù)據(jù),

13、僅僅代表具有一定邏輯含義的臨時(shí)數(shù)據(jù)。n(2)實(shí)例變量表示一些比較敏感的信息(比如銀行賬戶的口令),出于安全方面的原因,不希望對(duì)其序列化。n(3)實(shí)例變量需要按照用戶自定義的方式序列化,比如經(jīng)過(guò)加密后再序列化。在這種情況下,可以把實(shí)例變量定義為transient類型,然后在writeObject()方法中對(duì)其序列化。9.2.1 序列化對(duì)象圖n類與類之間可能存在關(guān)聯(lián)關(guān)系。以下代碼創(chuàng)建的三個(gè)對(duì)象之間的關(guān)聯(lián)關(guān)系。/客戶Tom有兩個(gè)訂單,訂單編號(hào)分別為“number1”和“number2”Customer2 customer=new Customer2(Tom);Order2 order1=new Or

14、der2(number1,customer);Order2 order2=new Order2(number2,customer);customer.addOrder(order1);customer.addOrder(order2);9.2.1 序列化對(duì)象圖9.2.1 序列化對(duì)象圖n當(dāng)通過(guò)ObjectOutputStream對(duì)象的writeObject(customer)方法序列化Customer2對(duì)象時(shí),會(huì)不會(huì)序列化與它關(guān)聯(lián)的Order2對(duì)象呢?答案是肯定的。n在默認(rèn)方式下,對(duì)象輸出流會(huì)對(duì)整個(gè)對(duì)象圖進(jìn)行序列化。當(dāng)程序執(zhí)行writeObject(customer)方法時(shí),該方法不僅序列化Cu

15、stomer2對(duì)象,還會(huì)把兩個(gè)與它關(guān)聯(lián)的Order2對(duì)象也進(jìn)行序列化。n當(dāng)通過(guò)ObjectInputStream對(duì)象的readObject()方法反序列化Customer2對(duì)象,實(shí)際上會(huì)對(duì)整個(gè)對(duì)象圖反序列化。9.2.1 序列化對(duì)象圖n按照默認(rèn)方式序列化對(duì)象A時(shí),實(shí)際上被序列化的對(duì)象圖中包括:對(duì)象A、對(duì)象B、對(duì)象C、對(duì)象D、對(duì)象E、對(duì)象F和對(duì)象G。9.2.2 控制序列化的行為n如果用戶希望控制類的序列化方式,可以在可序列化類中提供以下形式的writeObject()方法和readObject()方法:private void writeObject(java.io.ObjectOutputStr

16、eam out)throws IOExceptionprivate void readObject(java.io.ObjectInputStream in)throws IOException, ClassNotFoundException;9.2.2 控制序列化的行為n當(dāng)ObjectOutputStream對(duì)一個(gè)Customer對(duì)象進(jìn)行序列化時(shí),如果該Customer對(duì)象具有writeObject()方法,那么就會(huì)執(zhí)行這一方法,否則就按默認(rèn)方式序列化。n在Customer對(duì)象的writeObject()方法中,可以先調(diào)用ObjectOutputStream的defaultWriteObje

17、ct()方法,使得對(duì)象輸出流先執(zhí)行默認(rèn)的序列化操作。9.2.2 控制序列化的行為n當(dāng)ObjectInputStream對(duì)一個(gè)Customer對(duì)象進(jìn)行反序列化時(shí),如果該Customer對(duì)象具有readObject()方法,那么就會(huì)執(zhí)行這一方法,否則就按默認(rèn)方式反序列化。n在Customer對(duì)象的readObject()方法中,可以先調(diào)用ObjectInputStream的defaultReadObject()方法,使得對(duì)象輸入流先執(zhí)行默認(rèn)的反序列化操作。9.2.2 控制序列化的行為n在以下情況,可以考慮采用用戶自定義的序列化方式,從而控制序列化的行為:n(1)確保序列化的安全性,對(duì)敏感的信息加密

18、后再序列化,在反序列化時(shí)則需要解密。n(2)確保對(duì)象的成員變量符合正確的約束條件。n(3)優(yōu)化序列化的性能。n(4)便于更好的封裝類的內(nèi)部數(shù)據(jù)結(jié)構(gòu),確保類的接口不會(huì)被類的內(nèi)部實(shí)現(xiàn)所束縛。9.2.3 readResolve()方法在單例類中的運(yùn)用n單例類是指僅有一個(gè)實(shí)例的類。在系統(tǒng)中具有惟一性的組件可作為單例類,這種類的實(shí)例通常會(huì)占用較多的內(nèi)存,或者實(shí)例的初始化過(guò)程比較冗長(zhǎng),因此隨意創(chuàng)建這些類的實(shí)例會(huì)影響系統(tǒng)的性能。n如果一個(gè)類提供了readResolve()方法,那么在執(zhí)行反序列化操作時(shí),先按照默認(rèn)方式或者用戶自定義的方式進(jìn)行反序列化,最后再調(diào)用readResolve()方法,該方法返回的對(duì)象

19、為反序列化的最終結(jié)果。9.3 實(shí)現(xiàn)Externalizable接口nExternalizable接口繼承自Serializable接口。如果一個(gè)類實(shí)現(xiàn)了Externalizable接口,那么將完全由這個(gè)類控制自身的序列化行為。Externalizable接口中聲明了兩個(gè)方法:npublic void writeExternal(ObjectOutput out)throws IOException npublic void readExternal(ObjectInput in) throws IOException,ClassNotFoundException9.3 實(shí)現(xiàn)Externalizable接口nwriteExternal()方法負(fù)責(zé)序列化操作,readExternal()方法負(fù)責(zé)反序列化操作。在對(duì)實(shí)現(xiàn)了Externalizable接口的類的對(duì)象進(jìn)行反序列化時(shí),會(huì)先調(diào)用類的不帶參數(shù)的構(gòu)造方法,這是有別與默認(rèn)反序列化方式的。n由此可見(jiàn),一個(gè)類如果實(shí)現(xiàn)了Externalizable接口,那么它必須具有public類型的不帶參數(shù)的構(gòu)造方法,否則這個(gè)類無(wú)法反序列化。9.4 可序列化類的不同版本的序列化兼容性n假定Customer5類有兩個(gè)版本1.0和2.0,如果要把基于1.0的序列化數(shù)據(jù)反

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論