天天看點

序列化版本号(serialVersionUID)是做什麼用的

文章目錄

      • 1、為什麼要序列化
      • 2、序列化版本号的用處
      • 3、如何設定版本号
      • 4、自己試驗序列化、反序列化
      • 5、IDEA中如何自動生成serialVersionUID
      • 6、Transient 關鍵字
      • 7、序列化的對象範圍

1、為什麼要序列化

一些場景下需要把對象轉變成位元組序列

  • 儲存到存儲媒體上(磁盤等)
  • 用于網絡傳輸

一個很常見的應用是dubbo的RPC調用,如果參數是一個bean,那麼遠端調用的時候必然需要傳遞參數對象,這時候就必須将轉變為位元組序列(序列化)然後通過網絡傳輸

2、序列化版本号的用處

在 序列化存儲/反序列化讀取 或者是 序列化傳輸/反序列化接收 時,JVM 會把傳來的位元組流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認為是一緻的,可以進行反序列化,否則就會出現序列化版本不一緻的異常。

在對實體類進行不影響業務流程的更新時,比如隻追加了一個附加資訊字段,可以不改變序列化版本号,來實作新舊實體類的相容性(接收方的類裡沒有的字段被舍棄;多出來的字段賦初始值)。

3、如何設定版本号

  1. 手動控制版本号

實體類更新以後,可以手動控制版本号更新與否。

  1. 讓IDE根據類名、接口名、成員方法及屬性等來自動生成一個64位的哈希字段

大部分IDE都提供了自動生成這個哈希數的功能(對于實作了Serializable接口的類都有提示)。

  1. 不顯示定義 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)是不會被序列化儲存或者傳輸的,畢竟一個存在堆記憶體,一個存在方法區。

上一篇: @Transient