欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java自定義序列化的具體使用

 更新時(shí)間:2021年11月15日 15:14:42   作者:寫(xiě)不完作業(yè)還要玩  
本文主要介紹了java自定義序列化的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

1.問(wèn)題引出

在某些情況下,我們可能不想對(duì)于一個(gè)對(duì)象的所有field進(jìn)行序列化,例如我們銀行信息中的設(shè)計(jì)賬戶信息的field,我們不需要進(jìn)行序列化,或者有些field本省就沒(méi)有實(shí)現(xiàn)Serializable接口。

java中的序列化是遞歸序列化,也就是你的field的引用類(lèi)型中也有field可以被序列化,那么就會(huì)在序列化當(dāng)前對(duì)象的時(shí)候,一同序列化

2.解決辦法

使用transient(瞬變現(xiàn)象;過(guò)往旅客;候鳥(niǎo))關(guān)鍵字來(lái)修飾,該關(guān)鍵字只能修飾屬性,這樣在序列化的時(shí)候,這個(gè)屬性就會(huì)用默認(rèn)值,例如int類(lèi)型用0,引用對(duì)象用null;

但是使用transient關(guān)鍵字修飾的field雖然簡(jiǎn)單方便,但是會(huì)被完全隔離在序列化機(jī)制之外,這樣導(dǎo)致在反序列化回復(fù)java對(duì)象的時(shí)候,無(wú)法取得該field的值。

因此我們可以使用自定義序列化機(jī)制,可以讓程序控制如何序列化各field,甚至完全不序列化某些field(這樣就與transient相同),在序列化和反序列化過(guò)程中需要特殊處理的類(lèi)應(yīng)該提供如下特殊簽名的方法,這些特殊的方法用以實(shí)現(xiàn)自定義的序列化

private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in)throws IOException,ClassNotFoundException;
private void readObejctNoData()throws ObejctStreamException;

熱愛(ài)你所寫(xiě)的每一行的代碼

writeObject()方法負(fù)責(zé)寫(xiě)入特定類(lèi)的實(shí)例狀態(tài),通過(guò)重寫(xiě)這個(gè)方法,程序員可以完全獲得對(duì)序列化機(jī)制的控制,可以自主決定那些field需要序列化,需要怎么序列化,默認(rèn)情況(函數(shù)體為空)該方法會(huì)調(diào)用out.defaultWriteObject來(lái)保存java對(duì)象的各field,從而達(dá)到實(shí)現(xiàn)序列化java對(duì)象狀態(tài)的目的

readObject負(fù)責(zé)從流中讀取并且回復(fù)對(duì)象的field,通過(guò)重寫(xiě)該方法,程序員,可以獲得對(duì)反序列化機(jī)制的控制,對(duì)于反序列化各個(gè)field的順序應(yīng)該和序列化各個(gè)field的順序相同。

至于當(dāng)序列化流不完整時(shí),readObjectNoData可以正確的初始化反序列化的對(duì)象,例如接收方接收到的序列化流殘缺,或者序列化版本不同,則使用readObjectNoData來(lái)默認(rèn)的初始化。

例子(對(duì)于person的改寫(xiě)):

class Person implements Serializable
{
 private String name;
 private int age;
 public Person(String name,int age)
 {
  this.name=name;
  this.age=age;
 }
 //自動(dòng)生成的Get和Set方法
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
 private void writeObject(ObjectOutputStream out) throws IOException
 {
  //將名字翻轉(zhuǎn)之后寫(xiě)入二進(jìn)制流
  out.writeObject(new StringBuffer(this.name).reverse());
  out.writeInt(this.age);
 }
 private void readObject(ObjectInputStream in)throws IOException,ClassNotFoundException
 {
  this.name=((StringBuffer)in.readObject()).reverse().toString();
  //會(huì)拋出異常,因?yàn)檫@里的這樣寫(xiě)法導(dǎo)致同
  this.age=in.readInt();
 }
}

應(yīng)該提醒的是,這個(gè)自定義的功能十分強(qiáng)大

另外一種替換性的改寫(xiě):

//注意:這個(gè)方法由序列化機(jī)制調(diào)用,只要該方法存在就,它的訪問(wèn)控制符就可以為private protected package-private中的任意一種
 private Object writeReplace() throws ObjectStreamException
 {
  ArrayList<Object> list=new ArrayList<>();
  list.add(name);
  list.add(age);
  //我們這里返回ArrayList
  return list;
 }

序列化機(jī)制保證在序列化某個(gè)對(duì)象之前,先調(diào)用該對(duì)象的writeReplace方法,如果該方法返回另外一個(gè)java對(duì)象,系統(tǒng)就轉(zhuǎn)換為序列化writeReplace的返回結(jié)果。(ps:如果這個(gè)返回結(jié)果也有writeReplace方法的話,就繼續(xù)遞歸替代,直到?jīng)]有替換)

相應(yīng)與writeReplace相對(duì)的有一個(gè)readResolve方法,這個(gè)方法保護(hù)性的賦值整個(gè)對(duì)象,這里就不展開(kāi)討論了。

3.另外一種自定義序列化機(jī)制(介紹Externalizable)

Java還提供了另一種序列化機(jī)制,這種序列化方式完全由程序員決定存儲(chǔ)和恢復(fù)對(duì)象數(shù)據(jù)。要實(shí)現(xiàn)該目標(biāo),Java類(lèi)必須實(shí)現(xiàn)Externalizable接口,該接口里定義了如下兩個(gè)方法。

  • void readExternal(ObjectInput in):需要序列化的類(lèi)實(shí)現(xiàn)readExternal()方法來(lái)實(shí)現(xiàn)反序列化。該方法調(diào)用DataInput(它是ObjectInput的父接口)的方法來(lái)恢復(fù)基本類(lèi)型的Field值,調(diào)用ObjectInput的readObject()方法來(lái)恢復(fù)引用類(lèi)型的Field值。
  • void writeExternal(ObjectOutput out):需要序列化的類(lèi)實(shí)現(xiàn)writeExternal()方法來(lái)保存對(duì)象的狀態(tài)。該方法調(diào)用DataOutput(它是ObjectOutput的父接口)的方法來(lái)保存基本類(lèi)型的Field值,調(diào)用ObjectOutput的writeObject()方法來(lái)保存引用類(lèi)型的Field值。

具體的實(shí)現(xiàn)方式與上面自定義Serializable接口的實(shí)現(xiàn)類(lèi)的序列化是相同的操作,這里就不闡述了,下面圖是二者的比較。

到此這篇關(guān)于java自定義序列化的具體使用的文章就介紹到這了,更多相關(guān)java自定義序列化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論