瘋狂Java學習筆記(56)------------對象序列化
瘋狂Java學習筆記(56)------------對象序列化
所謂對象序列化就是將對象的狀態轉換成字節流,以后可以通過這些值再生成相同狀態的對象!
對象序列化是對象持久化的一種實現方法,它是將一個對象的屬性和方法轉化為一種序列化的格式以用于存儲和傳輸,反序列化就是根據這些保存的信息重建對象的過程。
java對象序列化機制一般來講有兩種用途:
1.需要將對象的狀態保存到文件中(存儲),而后能夠通過讀入對象狀態來重新構造對象,恢復程序狀態
2.使用套接字在網絡上傳送對象的程序來說,是很有用的(傳輸)。
我們通過讓類實現java.io.Serializable 接口可以將類序列化。這個接口是一個制造者(marker)接口。也就是說,對于要實現它的類來說,該接口不需要實現任何方法。它主要用來通知Java虛擬機(JVM),需要將一個對象序列化。
對于這個,有幾點我們需要明確:
1.并非所有類都可以序列化,在cmd下,我們輸入serialver java.net.socket,可以得到socket是否可序列化的信息,實際上socket是不可序列化的。
2.java有很多基礎類已經實現了serializable接口,比如string,vector等。但是比如hashtable就沒有實現serializable接口。
將對象讀出或者寫入流的主要類有兩個: ObjectOutputStream與ObjectInputStream 。
ObjectOutputStream 提供用來將對象寫入輸出流的writeObject方法, ObjectInputStream提供從輸入流中讀出對象的readObject方法。使用這些方法的對象必須已經被序列化的。
也就是說,必須已經實現Serializable接口。如果你想writeobject一個hashtable對象,那么,會得到一個異常。
在很多應用中,需要對某些對象進行序列化,讓它們離開內存空間,入住物理硬盤,以便長期保存。比如最常見的是Web服務器中的Session對象,當有 10萬用戶并發訪問,就有可能出現10萬個Session對象,內存可能吃不消,于是Web容器就會把一些seesion先序列化到硬盤中,等要用了,再把保存在硬盤中的對象還原到內存中。
當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個Java對象轉換為字節序列,才能在網絡上傳送;接收方則需要把字節序列再恢復為Java對象。
JDK類庫中的序列化API
java.io.ObjectOutputStream代表對象輸出流,它的writeObject(Object obj)方法可對參數指定的obj對象進行序列化,把得到的字節序列寫到一個目標輸出流中。
java.io.ObjectInputStream代表對象輸入流,它的readObject()方法從一個源輸入流中讀取字節序列,再把它們反序列化為一個對象,并將其返回。
只有實現了Serializable和Externalizable接口的類的對象才能被序列化。Externalizable接口繼承自 Serializable接口,實現Externalizable接口的類完全由自身來控制序列化的行為,而僅實現Serializable接口的類可以 采用默認的序列化方式 。
對象序列化包括如下步驟:
1) 創建一個對象輸出流,它可以包裝一個其他類型的目標輸出流,如文件輸出流;
2) 通過對象輸出流的writeObject()方法寫對象。
對象反序列化的步驟如下:
1) 創建一個對象輸入流,它可以包裝一個其他類型的源輸入流,如文件輸入流;
2) 通過對象輸入流的readObject()方法讀取對象。
對象序列化和反序列范例:
定義一個Person類,實現Serializable接口
[java] view plain copy
import java.io.Serializable;
/**
*
ClassName: Person
*
Description:測試對象序列化和反序列化
* @author xudp
* @version 1.0 V
* @createTime 2014-6-9 下午02:33:25
*/
public class Person implements Serializable {
/**
* 序列化ID
*/
private static final long serialVersionUID = -5809782578272943999L;
private int age;
private String name;
private String sex;
public int getAge() {
return age;
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setSex(String sex) {
this.sex = sex;
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;
/**
*
ClassName: TestObjSerializeAndDeserialize
*
Description: 測試對象的序列化和反序列
* @author xudp
* @version 1.0 V
* @createTime 2014-6-9 下午03:17:25
*/
public class TestObjSerializeAndDeserialize {
public static void main(String[] args) throws Exception {
SerializePerson();//序列化Person對象
Person p = DeserializePerson();//反序列Perons對象
System.out.println(MessageFormat.format("name={0},age={1},sex={2}",
p.getName(), p.getAge(), p.getSex()));
}
/**
* MethodName: SerializePerson
* Description: 序列化Person對象
* @author xudp
* @throws FileNotFoundException
* @throws IOException
*/
private static void SerializePerson() throws FileNotFoundException,
IOException {
Person person = new Person();
person.setName("gacl");
person.setAge(25);
person.setSex("男");
// ObjectOutputStream 對象輸出流,將Person對象存儲到E盤的Person.txt文件中,完成對Person對象的序列化操作
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
new File("E:/Person.txt")));
oo.writeObject(person);
System.out.println("Person對象序列化成功!");
oo.close();
}
/**
* MethodName: DeserializePerson
* Description: 反序列Perons對象
* @author xudp
* @return
* @throws Exception
* @throws IOException
*/
private static Person DeserializePerson() throws Exception, IOException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
new File("E:/Person.txt")));
Person person = (Person) ois.readObject();
System.out.println("Person對象反序列化成功!");
return person;
}
}
serialVersionUID的作用
簡單來說,Java的序列化機制是通過在運行時判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的字節流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認為是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常。(InvalidCastException)
舉個實際應用的例子:
為了實現系統交互的目的,我們需要系統之間通過網絡傳輸對象的實體(這些對象一般都是包括了系統中的一些數據)
Java序列化是一種解決方案:
系統A和B之間要進行交互,則A中的對象a首先會序列化,然后通過網絡傳輸到系統B,在B中經反序列化還原,然后對其進行操作,利用對象a所提供的數據。
但要實現這種方案對原來的系統有如下的要求:
交互的系統之間要存在完全一致的對象模型,這就需要對原來的系統進行比較大的改變,不符合我們的要求。
因為序列化傳輸的數據是二進制格式的,除非把這些二進制的數據反序列化為對象,否則我們根本不能對其數據進行處理,也不能看到里面包含的數據是什么。
要求交互的系統都是基于Java的,因為Java序列化只能應用與Java系統之中。
Serializable的作用
為什么一個類實現了Serializable接口,它就可以被序列化呢?在上節的示例中,使用ObjectOutputStream來持久化對象,在該類中有如下代碼:
Java 彈性文件服務
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。