1. 程式人生 > >java 序列化與反序列化(一)

java 序列化與反序列化(一)

在JAVA中,一個大的應用程式需要儲存很多物件的時候,由於虛擬機器記憶體有限,有時不可能所有有用的物件都放到記憶體中,因此,需要將不常用的物件暫時持久化的檔案中,當需要這個物件時,再從檔案把物件恢復到記憶體中,這就是所謂物件的序列化和反序列化。本文講實現如何將物件序列化到檔案,然後再從檔案反序列化到物件,你會發現其實特別簡單

先看一下物件的序列化和反序列化的關鍵是什麼

1,首先被序列化的物件必須實現 java.io.Serializable 介面,咳~~咳~~,其實這個介面沒定義任何方法

2,序列化時,需要用到物件輸出流ObjectOutputStream ,然後通過檔案輸出流構造

 ObjectOutputStream 物件呼叫writeObject寫入到檔案

3,反之,反序列化時用到物件輸入流ObjectIntputStream,  然後通過檔案輸出流構造 ObjectIntputStream物件呼叫readObject載入到記憶體,注意,是返回萬能Object型別

4,注意:序列化時transient變數(這個關鍵字的作用就是告知JAVA我不可以被序列化)和靜態變數不會被序列化(關於靜態變數不會序列化保留意見,本例項先不用靜態變數)

5,也是最應該注意的,如果你先序列化物件A後序列化B,那麼在反序列化的時候一定記著JAVA規定先讀到的物件是先被序列化的物件,不要先接收物件B,那樣會報錯

好了,現在我們做一個例項,我們現在要序列化一個會員物件到檔案裡,然後再把它讀出來

先建立會員類

Java程式碼
  1. import java.io.*;   
  2. import java.util.*;   
  3. //一定要實現Serializable接口才能被序列化   
  4. public class UserInfo implements Serializable {   
  5.     public String userName;   
  6.     public String userPass;   
  7.     //注意,userAge變數前面的transient   
  8.     public transient int userAge;   
  9.     public UserInfo(){   
  10.     }   
  11.     public UserInfo(String username,String userpass,int userage){   
  12.         this.userName=username;   
  13.         this.userPass=userpass;   
  14.         this.userAge=userage;   
  15.     }   
  16.     public String toString(){   
  17.         return "使用者名稱: "+this.userName+";密碼:"+this.userPass+   
  18.             ";年齡:"+this.userAge;   
  19.     }   
  20. }  

接著我們開始寫如何序列化和反序列化,初學認真看哦

Java程式碼
  1. import java.io.*;   
  2. import java.util.*;   
  3. public class Test {   
  4.     //序列化物件到檔案   
  5.     public static void serialize(String fileName){   
  6.         try  
  7.         {   
  8.             //建立一個物件輸出流,講物件輸出到檔案   
  9.             ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileName));   
  10.             out.writeObject("序列化日期是:");  //序列化一個字串到檔案   
  11.             out.writeObject(new Date());    //序列化一個當前日期物件到檔案   
  12.             UserInfo user=new UserInfo("renyanwei","888888",20);   
  13.             out.writeObject(user);  //序列化一個會員物件   
  14.             out.close();   
  15.         }   
  16.         catch (Exception x)   
  17.         {   
  18.             System.out.println(x.toString());   
  19.         }   
  20.     }   
  21.     //從檔案反序列化到物件   
  22.     public static void deserialize(String fileName){   
  23.         try  
  24.         {   
  25.             //建立一個物件輸入流,從檔案讀取物件   
  26.             ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileName));   
  27.             //注意讀物件時必須按照序列化物件順序讀,否則會出錯   
  28.             //讀取字串   
  29.             String today=(String)(in.readObject());   
  30.             System.out.println(today);   
  31.             //讀取日期物件   
  32.             Date date=(Date)(in.readObject());   
  33.             System.out.println(date.toString());   
  34.             //讀取UserInfo物件並呼叫它的toString()方法   
  35.             UserInfo user=(UserInfo)(in.readObject());             
  36.             System.out.println(user.toString());   
  37.             in.close();   
  38.         }   
  39.         catch (Exception x)   
  40.         {   
  41.             System.out.println(x.toString());   
  42.         }   
  43.     }   
  44.     public static void main(String[] args) {       
  45.         serialize("D:\\test.txt");   
  46.         System.out.println("序列化完畢");   
  47.         deserialize("D:\\test.txt");   
  48.         System.out.println("反序列化完畢");   
  49.     }   
  50. }  

執行結果:


序列化完畢
今天是:
Thu Oct 23 18:31:11 CST 2008
使用者名稱: renyanwei;密碼:888888;年齡:0
反序列化完畢

我們看程式碼總結一下,serialize方法實現了物件的序列化功能,講物件序列化到檔案,使用了檔案的輸出流ObjectOutputStream 的writerObject方法一次寫入一個物件,物件在檔案中按寫入順序儲存。

deserialize方法實現反序列化,從檔案將物件反序列化到記憶體,使用了ObjectIntputStream 的readObject方法,因為序列化物件是按照寫入順序儲存的,所以在反序列化時必須按照寫入順序讀取

大家看了結果就應該知道了,標明transit的例項變數是沒被序列化進去的 ,呵呵

其實序列化的意義不止如此,不但可以將物件放到檔案流,還可以放到網路流裡,比如我們做的Socket程式,你不但可以傳送給對方一行訊息,還可以傳送過去一個物件,我估計QQ就不止是把我們的訊息傳送到對方,應該是一個物件,裡面包含了傳送者的資訊什麼的。呵呵 有興趣的可以做一下哈