[TOC]java
Serializable 接口(序列化)
前言
查看API文檔時,就會發現
Serializable
接口是一個標記接口(沒有成員方法和變量),那麼他有什麼用呢?數據庫
- 序列化:能夠將一個對象(標誌對象的類型)及其狀態轉換爲字節碼,保存起來(能夠保存在數據庫,內存,文件等),而後能夠在適當的時候再將其狀態恢復(也就是反序列化)
- 一個類要想序列化就必須繼承java.io.Serializable接口,同時它的子類也能夠序列化(不用再繼承
Serializable
接口)。Serializable
接口,不只能夠本機,也能夠網絡操做,它自動屏蔽了操做系統的差別,字節順序等。- 序列化只能保存對象的非靜態成員變量,不能保存任何的成員方法和靜態的成員變量,並且序列化保存的只是變量的值,對於變量的任何修飾符都不能保存。記住序列化是保存對象的狀態。
用途
- 想把的內存中的對象狀態保存到一個文件中或者數據庫中時候。
- 想把對象經過網絡進行傳播的時候。
如何實現
- 原理:Java 序列化技術能夠使你將一個對象的狀態寫入一個Byte 流裏(系列化),而且能夠從其它地方把該Byte 流裏的數據讀出來(反序列化)。
- 經過
ObjectOutputStream
的writeObject()
方法把這個類的對象寫到一個地方(文件),再經過ObjectInputStream
的readObject()
方法把這個對象讀出來。
- 先寫一個實現序列化的類Person
class Person implements Serializable{ //序列化的關鍵常量 private static final long serialVersionUID = -3911255650485738676L; private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
- 用
ObjectOutputStream
的writeObject()
方法把這個類的對象寫到一個地方,再經過ObjectInputStream
的readObject()
方法把這個對象讀出來。
public static void main(String[] args) throws Exception { write(); read(); } public static void read() throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt")); Object obj = ois.readObject(); System.out.println(obj); ois.close(); } public static void write() throws Exception { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt")); Object obj = new Person("老王", 40); oos.writeObject(obj); oos.close(); } }
異常
-
java.io.NotSerializableException網絡
- 名稱:沒有序列化異常
- 緣由:在將對象保存到文件系統的時候沒有將對象實現序列化接口
- 解決:針對須要寫入到文件系統的對象實現對應的序列化接口
-
InvalidClassExceptionide
- 名稱:無效類異常
- 緣由:文件中保存的流的序列化id和本地類文件的序列化id不匹配(
serialVersionUID
) - 解決:保證id一致性
serialVersionUID
serialVersionUID
的取值是Java運行時環境根據類的內部細節自動生成的。若是對類的源代碼做了修改,再從新編譯,新生成的類文件的serialVersionUID
的取值有可能也會發生變化。- 類的
serialVersionUID
的默認值徹底依賴於Java編譯器的實現,對於同一個類,用不一樣的Java編譯器編譯,有可能會致使不一樣的serialVersionUID
,也有可能相同。通常給serialVersionUID
賦予明確的值。- 當經過網絡傳輸,因
serialVersionUID
不一致的時候就會報InvalidClassException
transient關鍵字
- 阻止實例中那些用此關鍵字聲明的變量持久化;當對象被反序列化時(從源文件讀取字節序列進行重構),這樣的實例變量值不會被持久化和恢復。
- 簡單的說:當某些變量不想被序列化,同是又不適合使用static關鍵字聲明,那麼此時就須要用transient關鍵字來聲明該變量。(不會再反序列化的時候被獲取數據,只會取得初始值,如 int 型的是 0,對象型的是 null。)
class Person implements Serializable{ //序列化的關鍵常量 private static final long serialVersionUID = -3911255650485738676L; private String name; //反序列化時不會獲取age值 private transient int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
以上this
@Fzxeyspa