Java Serializable 點滴經(jīng)驗
Serializable:可串行化的。 對象的串行化(Serialization) 串行化的定義 1. 什么是串行化 對象的壽命通常隨著生成該對象的程序的終止而終止,。有時候,,可能需要將對象的狀態(tài)保存下來,在需要時再將對象恢復(fù),。我們把對象的這種能記錄自己的狀態(tài)以便將來再生的能力,,叫做對象的持續(xù)性(persistence)。對象通過寫出描述自己狀態(tài)的數(shù)值來記錄自己,,這個過程叫對象的串行化(Serialization),。 2. 串行化的目的 串行化的目的是為java的運行環(huán)境提供一組特性,其主要任務(wù)是寫出對象實例變量的數(shù)值,。來源:www.examda.com 串行化方法 在java.io包中,,接口Serializable用來作為實現(xiàn)對象串行化的工具,只有實現(xiàn)了Serializable的類的對象才可以被串行化,。 1. 定義一個可串行化對象 public class Student implements Serializable{ private static final long serialVersionUID = 1L; int id; String name; int age; String department ;//系別 public Student(int id,String name,int age,String department){ this.id = id; this.name = name; this.age = age; this.department = department; } } 序列化運行時使用一個稱為 serialVersionUID 的版本號與每個可序列化類相關(guān)聯(lián),,該序列號在反序列化過程中用于驗證序列化對象的發(fā)送者和接收者是否為該對象加載了與序列化兼容的類。如果接收者加載的該對象的類的 serialVersionUID 與對應(yīng)的發(fā)送者的類的版本號不同,,則反序列化將會導(dǎo)致 InvalidClassException,。可序列化類可以通過聲明名為 "serialVersionUID" 的字段(該字段必須是靜態(tài) (static),、最終 (final) 的 long 型字段)顯式聲明其自己的 serialVersionUID: private static final long serialVersionUID = 1L;如果可序列化類未顯式聲明 serialVersionUID,,則序列化運行時將基于該類的各個方面計算該類的默認 serialVersionUID 值,如“Java(TM) 對象序列化規(guī)范”中所述。不過,,強烈建議 所有可序列化類都顯式聲明 serialVersionUID 值,,原因計算默認的 serialVersionUID 對類的詳細信息具有較高的敏感性,根據(jù)編譯器實現(xiàn)的不同可能千差萬別,,這樣在反序列化過程中可能會導(dǎo)致意外的 InvalidClassException,。因此,為保證 serialVersionUID 值跨不同 java 編譯器實現(xiàn)的一致性,,序列化類必須聲明一個明確的 serialVersionUID 值。還強烈建議使用 private 修改器顯示聲明 serialVersionUID(如果可能),,原因是這種聲明僅應(yīng)用于立即聲明類 -- serialVersionUID 字段作為繼承成員沒有用處,。 2. 構(gòu)造對象的輸入/輸出流 要串行化一個對象,必須與一定的對象輸入/輸出流聯(lián)系起來,,通過對象輸出流將對象狀態(tài)保存下來,,再通過對象輸入流將對象狀態(tài)恢復(fù)。 java.io包中,,提供了ObjectInputStream和ObjectOutputStream將數(shù)據(jù)流功能擴展至可讀寫對象,。在ObjectInputStream中用readObject()方法可以直接讀取一個對象,ObjectOutputStream中用writeObject()方法可以直接將對象保存到輸出流中,。來源:www.examda.com public static void main(String []args){ System.out.println("進入主方法了,。。,。"); Student stu=new Student(981036,"Liu Sui",18, "CSD"); //保存對象的狀態(tài) try{ FileOutputStream fo = new FileOutputStream("data.ser"); ObjectOutputStream so = new ObjectOutputStream(fo); so.writeObject(stu); so.close(); }catch(IOException e ) { e.printStackTrace(); } //恢復(fù)對象的狀態(tài) try{ FileInputStream fi=new FileInputStream("data.ser"); ObjectInputStream si=new ObjectInputStream(fi); try { stu=(Student)si.readObject(); System.out.println("student id="+stu.id); System.out.println("student name="+stu.name); System.out.println("student age="+stu.age); System.out.println("student department="+stu.department); } catch (ClassNotFoundException e) { e.printStackTrace(); } si.close(); }catch(IOException e ) { e.printStackTrace(); } } 在這個例子中,,我們首先定義一個類Student,實現(xiàn)了 Serializable接口,,然后通過對象輸出流的writeObject()方法將Student對象保存到文件data.ser中,。之后,通過對象輸入流的readObject()方法從文件data.ser中讀出保存下來的Student對象,。 串行化的注意事項 1.串行化能保存的元素 只能保存對象的非靜態(tài)成員變量,,不能保存任何的成員方法和靜態(tài)的成員變量,而且串行化保存的只是變量的值,,對于變量的任何修飾符,,都不能保存。 2.transient(短暫的, 瞬時的)關(guān)鍵字 對于某些類型的對象,,其狀態(tài)是瞬時的,,這樣的對象是無法保存其狀態(tài)的,例如一個Thread對象,,或一個FileInputStream對象,,對于這些字段,我們必須用transient關(guān)鍵字標明 3. 定制串行化 缺省的串行化機制,對象串行化首先寫入類數(shù)據(jù)和類字段的信息,,然后按照名稱的上升排列順序?qū)懭肫鋽?shù)值,。如果想自己明確地控制這些數(shù)值的寫入順序和寫入種類,必須定義自己的讀取數(shù)據(jù)流的方式,。就是在類的定義中重寫writeObject()和readObject()方法,。 例如可在例子中,加入重寫的writeObject()和readObject()方法,,對Student 類定制其串行化,。 private void writeObject(ObjectOutputStream out)throws IOException { out.writeInt(id); out.writeInt(age); out.writeUTF(name); out.writeUTF(department); } private void readObject(ObjectInputStream in)throws IOException { id=in.readInt(); age=in.readInt(); name=in.readUTF(); department=in.readUTF(); } public class Student implements Serializable{ }說白了就是: 實現(xiàn)了Serializable接口的對象轉(zhuǎn)換為字節(jié)序列,這些字節(jié)序列可以被完全存儲以備以后重新生成原來的對象,。也就是就是可以把對象存到字節(jié)流,,然后可以恢復(fù)!所以你想如果你的對象沒實現(xiàn)序列化怎么才能進行網(wǎng)絡(luò)傳輸呢,要網(wǎng)絡(luò)傳輸就得轉(zhuǎn)為字節(jié)流,所以在分布式應(yīng)用中,你就得實現(xiàn)序列化,如果你不需要分布式應(yīng)用,那就沒那個必要實現(xiàn)序列化. |
|