日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java对象序列化作用_Java学习之——理解对象序列化

發(fā)布時間:2025/4/5 java 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java对象序列化作用_Java学习之——理解对象序列化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Java的對象序列化就是把對象寫入到輸出流中,用來存儲或傳輸;反序列化就是從輸入流中讀取對象。簡單的來說是指將那些實現(xiàn)了Serializable接口的對象轉(zhuǎn)換成一個字節(jié)序列,并能夠在以后將這個字節(jié)序列完全恢復(fù)為原來的對象。

要序列化一個對象首先要創(chuàng)造某些OutputStream對象(如FileOutputStream、ByteArrayOutputStream等),然后將其封裝在一個ObjectOutputStream對象中,在調(diào)用writeObject()方法即可序列化一個對象;而反序列化的過程需要創(chuàng)造InputStream對象(如FileInputstream、ByteArrayInputStream等),然后將其封裝在ObjectInputStream中,在調(diào)用readObject()即可。注意 對象的序列化是基于字節(jié)的不能使用基于字符的流。

實現(xiàn)對象的序列化有兩種方式:(1)實現(xiàn)Serializable接口 (2)實現(xiàn)Externalible接口

一、序列化

1.第一種方式——實現(xiàn)Serializable接口。該接口僅為標記接口,不包含任何方法定義,表示實現(xiàn)了該接口的類可以被序列化,且實現(xiàn)該接口的類的所有子類都可以被序列化。而且實現(xiàn)了該接口的類默認為自動序列化,即對象中的所有字段都將被可序列化。但是有時候我們需要對某些字段不進行自動序列化(因為序列化會曝光信息),這時候我們就需要transient關(guān)鍵字(該關(guān)鍵字只能和Serializable對象一起使用)。被該關(guān)鍵字修飾的字段在自動序列化的過程中將不會被序列化。除了默認的自動序列化,我們也可以手動控制序列化過程,手動序列化甚至可以實現(xiàn)將被transient關(guān)鍵字修飾的字段序列化。要想實現(xiàn)手動序列化需要在實現(xiàn)了Serializable接口的類中添加兩個私有的方法writeObject()和readObject(),在這兩個方法中控制字段的序列化。

private void writeObject(ObjectOutputStream oos)throws IOException{

oos.defaultWriteObject();

oos.writeObject(password);

}第一行代碼是序列化所有非transient字段,必須是該方法的第一個操作

第二行代碼是序列化transient字段

private void readObject(ObjectInputStream ois)throws IOException,ClassNotFoundException{

ois.defaultReadObject();

password = (String)ois.readObject();

}

第一行代碼是反序列化所有非transient和非靜態(tài)字段,必須是該方法的第一個操作

第二行代碼是反序列化transient字段

這兩個方法會在序列化、反序列化的過程 中被自動調(diào)用。且不能關(guān)閉流,否則會導(dǎo)致序列化操作失敗。

2.第二種方式——實現(xiàn)Externalible接口。實現(xiàn)該接口需要定義一個默認的構(gòu)造函數(shù),否則將會拋出java.io.InvalidClassException異常。此外還需要定義兩個方法writeExternal()和readExternal()來控制序列化字段。

public void writeExternal(ObjectOutput out)throws IOException{

out.writeObject(name);

out.writeObject(password);

}

public void readExternal(ObjectIntput in)throws IOException,ClassNotFoundException{

name = in.readObject();

password = in.readObject();

}如果通過序列化將一個對象持久化寫入到文件中應(yīng)當注意以下情況:

(1)我們知道 FileOutputStream類有一個帶有兩個參數(shù)的重載Constructor——FileOutputStream(String,boolean)。若第二個參數(shù)為true且String代表的文件存在,那么將把新的內(nèi)容寫到原來文件的末尾而非重寫這個文件,這里我們不能用這個版本的構(gòu)造函數(shù),也就是說我們必須重寫這個文件,否則在讀取這個文件反序列化的過程中就會拋出異常,導(dǎo)致只有我們第一次寫到這個文件中的對象可以被反序列化,之后程序就會出錯。

(2)若一個類的字段有引用對象,那么在序列化該類的時候不僅該類要實現(xiàn)Serializable接口,這個引用類型也要實現(xiàn)Serializable接口。但有時我們并不需要對這個引用類型進行序列化,此時就需要使用transient關(guān)鍵字來修飾該引用類型保證在序列化的過程中跳過該引用類型。

(3)注意序列化操作保存的是對象的狀態(tài),靜態(tài)字段是類的狀態(tài)而不是對象的狀態(tài),所以不能序列化。

(4) 序列化前后對象的地址不同了,但是內(nèi)容是一樣的,而且對象中包含的引用也相同。換句話說,通過序列化操作,我們可以實現(xiàn)對任何可Serializable對象的”深度復(fù)制(deep copy)"——這意味著我們復(fù)制的是整個對象網(wǎng),而不僅僅是基本對象及其引用。對于同一流的對象,他們的地址是相同,說明他們是同一個對象,但是與其他流的對象地址卻不相同。也就說,只要將對象序列化到單一流中,就可以恢復(fù)出與我們寫出時一樣的對象網(wǎng),而且只要在同一流中,對象都是同一個。

(5)如果父類沒有實現(xiàn)Serializable接口,但其子類實現(xiàn) 了此接口,那么 這個子類是可以序列化的,但是在反序列化的過程 中會調(diào)用 父類 的無參構(gòu)造函數(shù),所以在其直接父類(注意是直接父類)中必須有一個無參的構(gòu)造函數(shù)。

(6)序列化輸出過程跟蹤寫入流的對象,試圖將同一個對象寫入流時,不會導(dǎo)致該對象被復(fù)制,而只是將一個句柄寫入流,該句柄指向流中相同對象的第一個對象出現(xiàn)的位置。為了避免這種情況,方法是在writeObject()之前調(diào)用out.reset()方法,這個方法的作用是清除流中保存的寫入對象的記錄。

《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的java对象序列化作用_Java学习之——理解对象序列化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。