更新時間:2020-10-29 17:39:49 來源:動力節點 瀏覽1051次
Java接口是一系列方法的聲明,是一些方法特征的集合,一個接口只有方法的特征沒有方法的實現,因此這些方法可以在不同的地方被不同的類實現,而這些實現可以具有不同的行為(功能)。而序列化 (Serialization)是將對象的狀態信息轉換為可以存儲或傳輸的形式的過程。Java序列化接口顧名思義,簡單地說,就是可以將一個對象(標志對象的類型)及其狀態轉換為字節碼,保存起來(可以保存在數據庫,內存,文件等),然后可以在適當的時候再將其狀態恢復(也就是反序列化)。
1 .Serializable接口
(1)serialization 不但可以在本機做,而且可以經由網絡操作。它自動屏蔽了操作系統的差異,字節順序等。比如,在 Windows 平臺生成一個對象并序列化之,然后通過網絡傳到一臺 Unix 機器上,然后可以在這臺Unix機器上正確地重構(deserialization)這個對象。 不必關心數據在不同機器上如何表示,也不必關心字節的順序或者其他任何細節。
另外,還應明白以下幾點:
a. java.io.Serializable接口沒有任何方法屬性域,實現它的類只是從語義上表明自己是可以序列化的。
b. 在對一個 Serializable(可序列化)對象進行重新裝配的過程中,不會調用任何構建器(甚至默認構建器)。整個對象都是通過從 InputStream 中取得數據恢復的。
c. 如是要一個類是可序列化的,那么它的子類也是可序列化的。
(2)serialVersionUID
serialVersionUID的取值是Java運行時環境根據類的內部細節自動生成的。如果對類的源代碼作了修改,再重新編譯,新生成的類文件的serialVersionUID的取值有可能也會發生變化。
類的serialVersionUID的默認值完全依賴于Java編譯器的實現,對于同一個類,用不同的Java編譯器編譯,有可能會導致不同的serialVersionUID,也有可能相同。為了提高哦啊serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。顯式地定義serialVersionUID有兩種用途:
a. 在某些場合,希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有相同的serialVersionUID;
b. 在某些場合,不希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有不同的serialVersionUID。
2.自定義序列化
自定義序列化是由ObjectInput/OutputStream在序列化/反序列化時候通過反射檢查該類是否存在以下方法(0個或多個):執行順序從上往下,序列化調用1和2,反序列調用3和4;transient關鍵字當某個字段被聲明為transient后,默認序列化機制就會忽略該字段。
1Object writeReplace() throws ObjectStreamException;可以通過此方法修改序列化的對象
2void writeObject(java.io.ObjectOutputStream out) throws IOException; 方法中調用defaultWriteObject() 使用writeObject的默認的序列化方式,除此之外可以加上一些其他的操作,如添加額外的序列化對象到輸出:out.writeObject("XX")
3void readObject(java.io.ObjectInputStream in) throws Exception; 方法中調用defaultReadObject()使用readObject默認的反序列化方式,除此之外可以加上一些其他的操作,如讀入額外的序列化對象到輸入:in.readObject()
4Object readResolve() throws ObjectStreamException;可以通過此方法修改返回的對象
例子:單例模式的類實現序列化接口,若使用默認的序列化策略,則在反序列化返回的對象不符合單利模式(反射創建了新的對象,如下PersonSington對象),可以通過修改序列化的readResolve來實現自定義序列化返回結果來實現單例對象唯一(相當于1,2,3方法對4的結果毫無作用)。
public class PersonSingleton implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private PersonSingleton(String name) {
this.name = name;
};
private static PersonSingleton person = null;
public static synchronized PersonSingleton getInstance() {
if (person == null)
return person = new PersonSingleton("cgl");
return person;
}
private Object writeReplace() throws ObjectStreamException {
System.out.println("1 write replace start");
return this;//可修改為其他對象
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
System.out.println("2 write object start");
out.defaultWriteObject();
//out.writeInt(1);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
System.out.println("3 read object start");
in.defaultReadObject();
//int i=in.readInt();
}
private Object readResolve() throws ObjectStreamException {
System.out.println("4 read resolve start");
return PersonSingleton.getInstance();//不管序列化的操作是什么,返回的都是本地的單例對象
}
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream(new File("D://person.dat"));
ObjectOutputStream op = new ObjectOutputStream(out);
op.writeObject(PersonSingleton.getInstance());
op.close();
FileInputStream in = new FileInputStream(new File("D://person.dat"));
ObjectInputStream oi = new ObjectInputStream(in);
Object person = oi.readObject();
in = new FileInputStream(new File("D://person.dat"));
oi = new ObjectInputStream(in);
PersonSinglton person1 = (PersonSinglton) oi.readObject();
System.out.println("sington person hashcode:" + person.hashCode());
System.out.println("sington person1 hashcode:" + person1.hashCode());
System.out.println("singleton getInstance hashcode:" + PersonSingleton.getInstance().hashCode());
System.out.println("singleton person equals:" + (person == PersonSingleton.getInstance()));
System.out.println("person equals1:" + (person1 == person));
}
}
運行結果:
write replace start
write object start
read object start
read resolve start
read object start
read resolve start
sington person hashcode:1550089733
sington person1 hashcode:1550089733
sington getInstance hashcode:1550089733
sington person equals:true
person equals1:true
3 Externalizable接口
Externalizable繼承于Serializable,當使用該接口時,序列化的細節需要由程序員去完成。若writeExternal()與readExternal()方法未作任何處理,那么該序列化行為將不會保存/讀取任何一個字段。出結果中所有字段的值均為空。
另外,若使用Externalizable進行序列化,當讀取對象時,會調用被序列化類的無參構造器去創建一個新的對象,然后再將被保存對象的字段的值分別填充到新對象中。由于這個原因,實現Externalizable接口的類必須要提供一個無參的構造器,且它的訪問權限為public。
以上就是為大家嘔心瀝血的整理的關于Java序列化接口的相關知識,相對于其他的Java接口知識點,Java序列化接口需要更多的時間去理解。觀看本站的Java接口教程,結合其他的Java知識,貫徹其中,才能徹底掌握Java序列化接口。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習