java - 為什麼Serializable中定義的Class 不能序列化?
Serialized 類別中的
Fields 本身必須是可序列化的或瞬態的,即使該類別從未明確序列化或反序列化。這是因為在負載下,大多數J2EE 應用程式框架都會將物件刷新到磁碟,而具有非瞬態、不可序列化資料成員的所謂可序列化物件可能會導致程式崩潰,並為攻擊者打開大門。
此規則在非可序列化欄位以及非私有欄位(因為可以在外部為它們分配非序列化值)以及在類別內為它們分配非序列化類型時引發集合欄位問題。
不合規程式碼範例
雷雷
一個物件序列化時,依照Java預設的序列化規則,物件內的所有成員都要序列化,也就是說,這些Class都必須實作Serializable。
所以,你有兩種改法,一是Address實作Serializable接口,二是對Person中的address成員加上
transient
標記,這樣該成員就不會被序列化進去。如果 address 成員需要進行序列化的話,則Address類別也需要實作Serializable介面。
如果 address 成員不需要進行序列化的話,可以加上transient關鍵字,則address成員不做序列化操作,值為null。如下:
當然還有其他方式:
例如實作Externalizable接口,重寫readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法。
還有一個替代實作Externalizable介面方法,還是實作Serializable接口,加入writeObject(ObjectOutputStream obs)和readObject(ObjectInputStream ois)方法。
再說說為什麼Address一定要實作Serializable,或是加上transient關鍵字Person才能進行序列化?
先看看不做處理,使用 ObjectOutputStream 來持久化對象,拋出的異常
看ObjectOutputStream源碼:
從此可知, 如果被寫入物件型別是String、Array、Enum、Serializable,就可以進行序列化,否則會拋出NotSerializableException。且在序列化物件時,不僅會序列化目前物件本身,還會對該物件引用的其它物件也進行序列化。