Java序列化接口Serializable接口的作用總結


一.Java序列化接口Serializable的作用:

一個對象有對應的一些屬性,把這個對象保存在硬盤上的過程叫做”持久化”.  

對象的默認序列化機制寫入的內容是:對象的類,類簽名,以及非瞬態和非靜態字段的值。(因為靜態static的東西在方法區.)

序列化能把堆內存中的對象的生命周期延長,做持久化操作.當下次再需要這個對象的時候,我們不用new了,直接從硬盤中讀取就可以了.(存儲到硬盤是一個文件,不需要我們去解析,如果用記事本打開解析會出現亂碼,解析要用特定的方式,不用我們管. 我們只需要讀取).  把對象存儲到硬盤上的一個文件中,這個文件的標准擴展名是(.object).

什么樣的數據會進行序列化到硬盤進行持久化?

①在很多框架中就會有這種.object結尾的文件,因為很多對象都不創建,創建起來太麻煩,直接讀取,而且有些對象的值你不知道,框架封存在.object文件中,直接讀取這個文件中的這個值就行了,不需要傳這個值.

在搞web開發的時候一些類就需要實現序列化接口,因為服務器就會對你的對象進行臨時本地存儲.它怕服務器崩了的以后,你的會話都被消失了.所以存儲在了硬盤上,你重新啟動服務器會恢復之前的會話,恢復對象,你之前運行的東西都在.

 

②對某些特點的對象,比如數據庫連接對象,存儲特定數據的對象 ,這樣對象你不想創建他們,想存儲起來,讓他們的生命周期延長,可以把他們放在硬盤當中.每次系統啟動的時候都到.object中讀取對象和里面的數據,這個時候就可以把他們序列化來完成.

二.具體舉例:

Person.java

 1 import java.io.Serializable;
 2 /*
 3  * Serializable:用於給被序列化的類加入ID號。
 4  * 用於判斷類和對象是否是同一個版本。 
 5  */
 6 public class Person implements Serializable/*標記接口*/ {
 7     /**
 8      * transient:非靜態數據不想被序列化可以使用這個關鍵字修飾。 
 9      */
10     private static final long serialVersionUID = 9527l; 
11 //    private transient String name;
12     private  String name;
13 //    private static int age;
14     private int age;
15 
16     public Person(String name, int age) {
17         super();
18         this.name = name;
19         this.age = age;
20     }
21     public String getName() {
22         return name;
23     }
24     public void setName(String name) {
25         this.name = name;
26     }
27     public int getAge() {
28         return age;
29     }
30     public void setAge(int age) {
31         this.age = age;
32     }
33 }

ObjectStreamDemo.java

 1  public class ObjectStreamDemo {
 2      /**
 3       * @param args
 4       * @throws IOException 
 5       * @throws ClassNotFoundException 
 6       */
 7      public static void main(String[] args) throws IOException, ClassNotFoundException {
 8          //writeObj();
 9          readObj();
10      }
11      public static void readObj() throws IOException, ClassNotFoundException {
12          ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
13          //對象的反序列化。 
14          Person p = (Person)ois.readObject();
15          System.out.println(p.getName()+":"+p.getAge());
16          ois.close();
17      }
18  
19      public static void writeObj() throws IOException, IOException {
20          
21          ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
22          //對象序列化。  被序列化的對象必須實現Serializable接口。 
23          oos.writeObject(new Person("小強",30));
24          oos.close();
25      }
26  }

 

上面的例子中當你一開始對這個person類進行序列化的時候用的是private類型序列化的,但是你在反序列化之前,把這個private改成了public.這樣反序列化讀取的時候就會報出異常.

Exception in thread "main" java.io.InvalidClassException: cn.itcast.serializable.Person; local class incompatible: stream classdesc serialVersionUID = 9527, local class serialVersionUID = 7915096815468332737

就是關於前后這個Person類的版本號不統一.如果加上設定一個版本號,那么經過上面的修改也是可以反序列化的.

可能拋出的錯誤 @throws ClassNotFoundException

如果只有obj.object 這個文件能不能把其中的對象Person取出來,因為任何對象在堆內存中創建都必須依賴於該對象所屬的類文件(class文件),如果僅僅給了obj.object,這個里面有Person對象的字節碼,可是取出的時候你內存中並沒有Person.class文件,沒有,所以取不出來,所以必須要有obj.object文件和Person.class文件.(所以有一個ClassNotFound異常)

關於程序中的類 ObjectInputStream和ObjectOutputStream 

ObjectInputStream 對以前使用 ObjectOutputStream 寫入的基本數據和對象進行反序列化(意思就是ObjectInputStream只能讀取ObjectOutputStream的)

ObjectOutputStream 和 ObjectInputStream 分別與 FileOutputStream 和 FileInputStream 一起使用時,可以為應用程序提供對對象的持久存儲。

關於SerializableID

SerializableID號是根據類的特征和類的簽名算出來的.為什么ID號那么長,是因為為了避免重復.所以Serializable是給類加上id用的. 用於判斷類和對象是否是同一個版本。

如果可序列化類未顯式聲明 serialVersionUID,則序列化運行時將基於該類的各個方面計算該類的默認 serialVersionUID 值. 原因是計算默認的 serialVersionUID 對類的詳細信息具有較高的敏感性,根據編譯器實現的不同可能千差萬別,這樣在反序列化過程中可能會導致意外的 InvalidClassException

//====================================================================

具體示例可以看我的如下博文(轉載+總結):

http://www.cnblogs.com/DreamDrive/p/5412931.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM