JAVA Serialization 基礎介紹

對象的串行化(Serialization)
 
一、串行化的概念和目的 

1.什麼是串行化 

            對象的壽命通常隨着生成該對象的程序的終止而終止。有時候,可能需要將對象的狀態保存下來,在需要時再將對象恢復。我們把對象的這種能記錄自己的狀態以便將來再生的能力。叫作對象的持續性(persistence)。對象通過寫出描述自己狀態的數值來記錄自己 ,這個過程叫對象的串行化(Serialization) 。串行化的主要任務是寫出對象實例變量的數值。如果交量是另一對象的引用,則引用的對象也要串行化。這個過程是遞歸的,串行化可能要涉及一個複雜樹結構的單行化,包括原有對象、對象的對象、對象的對象的對象等等。對象所有權的層次結構稱爲圖表(graph)。 


2.串行化的目的 

           Java對象的單行化的目標是爲Java的運行環境提供一組特性,如下所示: 

1)       儘量保持對象串行化的簡單扼要 ,但要提供一種途徑使其可根據開發者的要求進行擴展或定製。 

2)       串行化機制應嚴格遵守Java的對象模型 。對象的串行化狀態中應該存有所有的關於種類的安全特性的信息。 

3)       對象的串行化機制應支持Java的對象持續性。 

4)       對象的串行化機制應有足夠的 可擴展能力以支持對象的遠程方法調用(RMI)。 

5)       對象串行化應允許對象定義自身 的格式即其自身的數據流表示形式,可外部化接口來完成這項功能。
 
 二、串行化方法 
            從JDK1.1開始,Java語言提供了對象串行化機制 ,在java.io包中,接口Serialization用來作爲實現對象串行化的工具 ,只有實現了Serialization的類的對象纔可以被串行化。 
            Serializable接口中沒有任何的方法。當一個類聲明要實現Serializable接口時,只是表明該類參加串行化協議,而不需要實現任何特殊的方法。下面我們通過實例介紹如何對對象進行串行化。 

1.定義一個可串行化對象 

           一個類,如果要使其對象可以被串行化,必須實現Serializable接口。我們定義一個類Student如下:
import java.io.Serializable;   
  public class Student implements Serializable {   
    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;   
      }   
  }  
2.構造對象的輸入/輸出流 

           要串行化一個對象,必須與一定的對象輸出/輸入流聯繫起來,通過對象輸出流將對象狀態保存下來,再通過對象輸入流將對象狀態恢復。 

            java.io包中,提供了ObjectInputStream和ObjectOutputStream將數據流功能擴展至可讀寫對象 。在ObjectInputStream 中用readObject()方法可以直接讀取一個對象,ObjectOutputStream中用writeObject()方法可以直接將對象保存到輸出流中。
import java.io.FileInputStream;   
import java.io.FileOutputStream;   
import java.io.IOException;   
import java.io.ObjectInputStream;   
import java.io.ObjectOutputStream;   
  
public class ObjectSer {   
  
    public static void main(String args[]) throws IOException,   
            ClassNotFoundException {   
  
        Student stu = new Student(981036, "LiuMing", 18, "CSD");   
  
        FileOutputStream fo = new FileOutputStream("data.ser");   
  
        ObjectOutputStream so = new ObjectOutputStream(fo);   
  
        try {   
             so.writeObject(stu);   
              so.close();   
  
        } catch (IOException e) {   
            System.out.println(e);   
        }   
          stu = null;   
          FileInputStream fi = new FileInputStream("data.ser");   
          ObjectInputStream si = new ObjectInputStream(fi);   
  
        try {   
              stu = (Student) si.readObject();   
              si.close();   
  
        } catch (IOException e)   
  
        {   
            System.out.println(e);   
        }   
          System.out.println("Student Info:");   
          System.out.println("ID:" + stu.id);   
          System.out.println("Name:" + stu.name);   
          System.out.println("Age:" + stu.age);   
          System.out.println("Dep:" + stu.department);     
    }   
  
}  
運行結果如下:
        Student Info: 
     ID:981036 
  Name:LiuMing 
  Age:18 
  Dep:CSD
 
            在這個例子中,我們首先定義了一個類Student,實現了Serializable接口 ,然後通過對象輸出流的writeObject()方法將Student對象保存到文件 data.ser中 。之後,通過對家輸入流的readObjcet()方法從文件data.ser中讀出保存下來的Student對象 。從運行結果可以看到,通過串行化機制,可以正確地保存和恢復對象的狀態。 

三、串行化的注意事項 
1.串行化能保存的元素 

            串行化只能保存對象的非靜態成員交量,不能保存任何的成員方法和靜態的成員變量,而且串行化保存的只是變量的值,對於變量的任何修飾符都不能保存。 

2.transient關鍵字 

            對於某些類型的對象,其狀態是瞬時的,這樣的對象是無法保存其狀態的。例如一個Thread對象或一個FileInputStream對象 ,對於這些字段,我們必須用transient關鍵字標明,否則編譯器將報措。 

            另外 ,串行化可能涉及將對象存放到 磁盤上或在網絡上發達數據,這時候就會產生安全問題。因爲數據位於Java運行環境之外,不在Java安全機制的控制之中。對於這些需要保密的字段,不應保存在永久介質中 ,或者不應簡單地不加處理地保存下來 ,爲了保證安全性。應該在這些字段前加上transient關鍵字。
下面是java規範中對transient關鍵字的解釋:   
      The   transient   marker   is   not   fully   specified   by   The   Java   Language     Specification   but   is   used   in   object   serialization   to   mark   member   variables   that   should   not   be   serialized.
 
 以下是transient的一個應用舉例:
 
 //LoggingInfo.java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
public class LoggingInfo implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Date loggingDate = new Date();
private String uid;
private transient String pwd;
LoggingInfo(String user, String password) {
uid = user;
pwd = password;
}
public String toString() {
String password = null;
if (pwd == null) {
password = "NOT SET";
} else {
password = pwd;
}
return "logon info: \n   " + "user: " + uid + "\n   logging date : "
+ loggingDate.toString() + "\n   password: " + password;
}
public static void main(String[] args) {
LoggingInfo logInfo = new LoggingInfo("MIKE", "MECHANICS");
System.out.println(logInfo.toString());
try {
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(
"logInfo.out"));
o.writeObject(logInfo);
o.close();
} catch (Exception e) {// deal with exception
}
// To read the object back, we can write
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(
"logInfo.out"));
LoggingInfo logInfo1 = (LoggingInfo) in.readObject();
System.out.println(logInfo1.toString());
} catch (Exception e) {// deal with exception
}
}
}
  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章