java对象序列化作用_Java学习之——理解对象序列化
Java的對象序列化就是把對象寫入到輸出流中,用來存儲或傳輸;反序列化就是從輸入流中讀取對象。簡單的來說是指將那些實現了Serializable接口的對象轉換成一個字節序列,并能夠在以后將這個字節序列完全恢復為原來的對象。
要序列化一個對象首先要創造某些OutputStream對象(如FileOutputStream、ByteArrayOutputStream等),然后將其封裝在一個ObjectOutputStream對象中,在調用writeObject()方法即可序列化一個對象;而反序列化的過程需要創造InputStream對象(如FileInputstream、ByteArrayInputStream等),然后將其封裝在ObjectInputStream中,在調用readObject()即可。注意 對象的序列化是基于字節的不能使用基于字符的流。
實現對象的序列化有兩種方式:(1)實現Serializable接口 (2)實現Externalible接口
一、序列化
1.第一種方式——實現Serializable接口。該接口僅為標記接口,不包含任何方法定義,表示實現了該接口的類可以被序列化,且實現該接口的類的所有子類都可以被序列化。而且實現了該接口的類默認為自動序列化,即對象中的所有字段都將被可序列化。但是有時候我們需要對某些字段不進行自動序列化(因為序列化會曝光信息),這時候我們就需要transient關鍵字(該關鍵字只能和Serializable對象一起使用)。被該關鍵字修飾的字段在自動序列化的過程中將不會被序列化。除了默認的自動序列化,我們也可以手動控制序列化過程,手動序列化甚至可以實現將被transient關鍵字修飾的字段序列化。要想實現手動序列化需要在實現了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和非靜態字段,必須是該方法的第一個操作
第二行代碼是反序列化transient字段
這兩個方法會在序列化、反序列化的過程 中被自動調用。且不能關閉流,否則會導致序列化操作失敗。
2.第二種方式——實現Externalible接口。實現該接口需要定義一個默認的構造函數,否則將會拋出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();
}如果通過序列化將一個對象持久化寫入到文件中應當注意以下情況:
(1)我們知道 FileOutputStream類有一個帶有兩個參數的重載Constructor——FileOutputStream(String,boolean)。若第二個參數為true且String代表的文件存在,那么將把新的內容寫到原來文件的末尾而非重寫這個文件,這里我們不能用這個版本的構造函數,也就是說我們必須重寫這個文件,否則在讀取這個文件反序列化的過程中就會拋出異常,導致只有我們第一次寫到這個文件中的對象可以被反序列化,之后程序就會出錯。
(2)若一個類的字段有引用對象,那么在序列化該類的時候不僅該類要實現Serializable接口,這個引用類型也要實現Serializable接口。但有時我們并不需要對這個引用類型進行序列化,此時就需要使用transient關鍵字來修飾該引用類型保證在序列化的過程中跳過該引用類型。
(3)注意序列化操作保存的是對象的狀態,靜態字段是類的狀態而不是對象的狀態,所以不能序列化。
(4) 序列化前后對象的地址不同了,但是內容是一樣的,而且對象中包含的引用也相同。換句話說,通過序列化操作,我們可以實現對任何可Serializable對象的”深度復制(deep copy)"——這意味著我們復制的是整個對象網,而不僅僅是基本對象及其引用。對于同一流的對象,他們的地址是相同,說明他們是同一個對象,但是與其他流的對象地址卻不相同。也就說,只要將對象序列化到單一流中,就可以恢復出與我們寫出時一樣的對象網,而且只要在同一流中,對象都是同一個。
(5)如果父類沒有實現Serializable接口,但其子類實現 了此接口,那么 這個子類是可以序列化的,但是在反序列化的過程 中會調用 父類 的無參構造函數,所以在其直接父類(注意是直接父類)中必須有一個無參的構造函數。
(6)序列化輸出過程跟蹤寫入流的對象,試圖將同一個對象寫入流時,不會導致該對象被復制,而只是將一個句柄寫入流,該句柄指向流中相同對象的第一個對象出現的位置。為了避免這種情況,方法是在writeObject()之前調用out.reset()方法,這個方法的作用是清除流中保存的寫入對象的記錄。
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的java对象序列化作用_Java学习之——理解对象序列化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java8函数式编程 视频_快速掌握Ja
- 下一篇: toto马桶水箱一直流水怎么修视频?