文章目錄
-
-
- 1、為什麼要序列化
- 2、序列化版本号的用處
- 3、如何設定版本号
- 4、自己試驗序列化、反序列化
- 5、IDEA中如何自動生成serialVersionUID
- 6、Transient 關鍵字
- 7、序列化的對象範圍
-
1、為什麼要序列化
一些場景下需要把對象轉變成位元組序列
- 儲存到存儲媒體上(磁盤等)
- 用于網絡傳輸
一個很常見的應用是dubbo的RPC調用,如果參數是一個bean,那麼遠端調用的時候必然需要傳遞參數對象,這時候就必須将轉變為位元組序列(序列化)然後通過網絡傳輸
2、序列化版本号的用處
在 序列化存儲/反序列化讀取 或者是 序列化傳輸/反序列化接收 時,JVM 會把傳來的位元組流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認為是一緻的,可以進行反序列化,否則就會出現序列化版本不一緻的異常。
在對實體類進行不影響業務流程的更新時,比如隻追加了一個附加資訊字段,可以不改變序列化版本号,來實作新舊實體類的相容性(接收方的類裡沒有的字段被舍棄;多出來的字段賦初始值)。
3、如何設定版本号
- 手動控制版本号
實體類更新以後,可以手動控制版本号更新與否。
- 讓IDE根據類名、接口名、成員方法及屬性等來自動生成一個64位的哈希字段
大部分IDE都提供了自動生成這個哈希數的功能(對于實作了Serializable接口的類都有提示)。
- 不顯示定義 serialVersionUID 。
在這種情況下 jvm 會根據類的内容自動生成 serialVersionUID,如果對類的源代碼作了修改,再重新編譯,新生成的類檔案的serialVersionUID值會發生變化。
而且類的serialVersionUID的預設值完全依賴于Java編譯器的實作,對于同一個類,用不同的Java編譯器編譯,也有可能會導緻不同的serialVersionUID。
4、自己試驗序列化、反序列化
想學習序列化相關知識,自己做試驗時,一種方法是可以簡單地使用dubbo的遠端調用;
另外也可以像下面這樣做對象的儲存和讀取
public void saveObject() {
try {
FileOutputStream fos = new FileOutputStream(new File("FileFullpath&Name"));
ObjectOutputStream os = new ObjectOutputStream(fos);
SerializableDemo s = new SerializableDemo();
os.writeObject(s);
os.flush();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readObject() {
try {
FileInputStream fis = new FileInputStream(new File("FileFullpath&Name"));
ObjectInputStream ois = new ObjectInputStream(fis);
SerializableDemo s2 = (SerializableDemo) ois.readObject();
System.out.println(s2.getB());
ois.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
5、IDEA中如何自動生成serialVersionUID
與Eclipse不同,IDEA并沒有提供自動生成serialVersionUID的功能,可以通過安裝 GenerateSerialVersionUID 插件來解決這個問題。
6、Transient 關鍵字
Transient 關鍵字的作用是控制變量的序列化,在變量聲明前加上該關鍵字,可以阻止該變量被序列化到檔案中,在被反序列化後,transient 變量的值被設為初始值。
除了使用 Transient 關鍵字以外,還可以将不需要被序列化的字段抽取出來放到父類中,子類實作 Serializable 接口,父類不實作,根據父類序列化規則,父類的字段資料将不被序列化。
7、序列化的對象範圍
在有些情況下,要注意一個容易混淆的問題:序列化針對的是“對象”,類的成員變量(static)是不會被序列化儲存或者傳輸的,畢竟一個存在堆記憶體,一個存在方法區。