標籤:
Java對象序列化和還原序列化
在Java中,我們如果要儲存一個對象的瞬時狀態值,以便在下次使用時能夠得到這些值,或者持久化對象,或者使用RMI(遠程方法調用),或在網路中傳遞對象時,此時我們就需要將對象序列化,實現序列化,我們只要實現Serializable介面,該介面是一個標記介面(Tag interface),即裡面沒有方法,其主要作用就是告訴JVM該類的對象可以進行序列化。
一般來說,很多類的對象都實現了Serializable介面,但是,有些對象是不能進行序列化的,比如與資料庫相關的連線物件,file對象等等,儲存這些對象的狀態值是沒有意義的,因此Object並沒有實現Serializable介面也是這個原因,若想要將對象序列化,我們只要實現Serializable介面即可,一個類的父類實現了Serializable介面,則其子類預設也會實現該介面,反過來,若其子類需要序列化,則其父類必須要實現Serializable介面。
序列化是為了儲存對象的狀態,因此,static類型的變數不會被序列化,因為儲存其值是沒有意義的,它會在運行過程中動態變化的,對於參考型別的變數,或者其引用變數中又包含引用變數,我們在序列化該對象時,都對其進行了序列化,我們只要確保他們都實現了Serializable介面。
在序列化的過程中,如果對於有些變數,我們不希望儲存其值,那麼我們在該引用變數或者原始變數名前加上關鍵字transient即可,這樣,該欄位就不會被序列化了,在還原序列化恢複成對象時,其預設值為null(欄位為物件類型)或者原始類型的預設值(原始類型變數)。
在還原序列化時,JVM將序列化的對象進行重新組裝,然後在heap中開闢空間,產生相應類型的對象,在該過程中,其並不調用構造器。當然,我們我們如果不想使用java提供的預設的序列化方式,我們只要實現Externalizable介面即可,當讀取對象時,會調用被序列化類別的無參構造器去建立一個新的對象,然後再將被儲存對象的欄位的值分別填充到新對象中。用該介面時,序列化的細節需要由程式員去完成。
舉例如下:
package com.test;import java.io.Serializable;/** * Created by siege on 2015-07-28. */public class Person implements Serializable { private transient int num=3; private transient String description="hello"; private static int count; private String name; private int age; public Person(String name, int age) { count++; this.name = name; this.age = age; } @Override public String toString() { return "name"+":"+name+",age:"+age+",count:"+count+",num:"+num+",description:"+description; }}
package com.test;import java.io.*;/** * Created by siege on 2015-07-28. */public class SerializableTest { public static void main(String[] args) { Person person1=new Person("siege1",20); Person person2=new Person("siege2",21); Person person3=new Person("siege3",22); try { FileOutputStream fos=new FileOutputStream("C:\\test\\person.out"); ObjectOutputStream objectOutputStream=new ObjectOutputStream(fos); objectOutputStream.writeObject(person1); objectOutputStream.writeObject(person2); objectOutputStream.writeObject(person3); objectOutputStream.close(); } catch (java.io.IOException e) { e.printStackTrace(); } try { FileInputStream fin=new FileInputStream("C:\\test\\person.out"); ObjectInputStream objectInputStream=new ObjectInputStream(fin); try { Person p1=(Person)objectInputStream.readObject(); Person p2=(Person)objectInputStream.readObject(); Person p3=(Person)objectInputStream.readObject(); System.out.println(p1); System.out.println(p2); System.out.println(p3); } catch (ClassNotFoundException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } }}
輸出結果如下:
name:siege1,age:20,count:3,num:0,description:null
name:siege2,age:21,count:3,num:0,description:null
name:siege3,age:22,count:3,num:0,description:null
由此可見,static變數的值是在我們還原序列化之後再從類變數中取出放入對象中的,同時,transient類型的變數沒有序列化,還原序列化的值為預設值。
若Person沒有實現Serializable介面,則會出現
java.io.NotSerializableException
錯誤。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Java對象序列化和還原序列化