Java 物件實現 Serializable 的原因

Zhang_Xiang發表於2022-05-22

java.io.Serializable 是 Java 中的一種標記介面(marker interface)。標記介面是一種特殊的介面,java.io.Serializable 介面沒有任何方法,也沒有常量。

物件序列化是將物件轉換為靜態有序的位元組流的過程,因此該物件可以用於傳輸或持久化。反序列化是該過程的反向操作,即將位元組流轉換為 Java 物件。Java 物件實現 java.io.Serializable 該介面後,就能實現序列化和反序列化。序列化在遠端呼叫中非常常見。

暴露實體

定義 member 實體如下:

@Data  
public class Mbr implements java.io.Serializable {  
  
    private Long id;  
  
    private String name;  
  
    private String age; 
}

我們在實踐中,可能會遇到不定義 dto 物件,直接在介面中暴露實體物件 create(Mbr mbr),update(Mbr mbr) 的情況,這時實體物件必須實現 java.io.Serializable 介面。

當實體實現了 java.io.Serializable 介面後,所有繼承它的實體也能被序列化。如果實體裡引用了其它物件,那麼被引用的物件也應該可以序列化。

@Data  
public class Mbr implements java.io.Serializable {  
  
    private Long id;  
  
    private String name;  
  
    private String age; 

	// Address 應該也實現 java.io.Serializable 介面
	private Address address;
}

serialVersionUID

@Data  
public class Mbr implements java.io.Serializable {  

	private static final long serialVersionUID = 1L;
  
    private Long id;  
  
    private String name;  
  
    private String age; 
}

JVM 通過版本號(serialVersionUID) 將序列化的實體聯絡起來。在反序列化的過程中,JVM 會將位元組流中的 serialVersionUID 與本地響應的實體類中的 serialVersionUID 比較,相同,可以序列化,否則丟擲 InvaidCastException

當實體中不定義 serialVersionUID 欄位時,JVM 將在執行時生成該欄位。所以,這裡的重點是,在開發過程中經常會變更欄位,如果不定義 serialVersionUID 欄位,執行時每次都會生成不同的 serialVersionUID,導致 _InvalidClassExceptions_ 異常。
這種問題還是挺常見的,在微服務 A 中引用另一個微服務 B 的實體(或 dto)包,B 中的實體更新,但沒有更新 A 中的應用,就會引發此問題。

相關文章