鴻蒙OS Serializable

2022-10-17 16:09 更新

Serializable

public interface Serializable

類的可序列化性由實現(xiàn) java.io.Serializable 接口的類啟用。未實現(xiàn)此接口的類將不會對其任何狀態(tài)進行序列化或反序列化??尚蛄谢惖乃凶宇愋捅旧矶际强尚蛄谢?。序列化接口沒有方法或字段,僅用于識別可序列化的語義。

為了允許序列化不可序列化類的子類型,子類型可以負責保存和恢復超類型的公共、受保護和(如果可訪問)包字段的狀態(tài)。僅當它擴展的類具有可訪問的無參數(shù)構造函數(shù)來初始化類的狀態(tài)時,子類型才可以承擔此責任。如果不是這種情況,則聲明類 Serializable 是錯誤的。將在運行時檢測到錯誤。

在反序列化過程中,不可序列化類的字段將使用類的公共或受保護的無參數(shù)構造函數(shù)進行初始化??尚蛄谢淖宇惐仨毧梢栽L問無參數(shù)構造函數(shù)??尚蛄谢宇惖淖侄螌牧髦谢謴?。

在遍歷圖時,可能會遇到不支持 Serializable 接口的對象。在這種情況下,NotSerializableException 將被拋出,并將識別不可序列化對象的類。

在序列化和反序列化過程中需要特殊處理的類必須實現(xiàn)具有這些確切簽名的特殊方法:

 private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;
 private void readObjectNoData()
     throws ObjectStreamException;

writeObject 方法負責為其特定類寫入對象的狀態(tài),以便相應的 readObject 方法可以恢復它??梢酝ㄟ^調用 out.defaultWriteObject 來調用保存 Object 字段的默認機制。該方法不需要關注屬于其超類或子類的狀態(tài)。通過使用 writeObject 方法或使用 DataOutput 支持的原始數(shù)據類型的方法將各個字段寫入 ObjectOutputStream 來保存狀態(tài)。

readObject 方法負責從流中讀取并恢復類字段。它可以調用 in.defaultReadObject 來調用用于恢復對象的非靜態(tài)和非瞬態(tài)字段的默認機制。 defaultReadObject 方法使用流中的信息將保存在流中的對象的字段分配給當前對象中相應命名的字段。這可以處理類已經演變?yōu)樘砑有伦侄蔚那闆r。該方法不需要關注屬于其超類或子類的狀態(tài)。通過使用 writeObject 方法或使用 DataOutput 支持的原始數(shù)據類型的方法將各個字段寫入 ObjectOutputStream 來保存狀態(tài)。

如果序列化流未將給定類列為被反序列化對象的超類,readObjectNoData 方法負責為其特定類初始化對象的狀態(tài)。這可能發(fā)生在接收方使用與發(fā)送方不同版本的反序列化實例類的情況下,并且接收方的版本擴展了發(fā)送方版本未擴展的類。如果序列化流已被篡改,也可能發(fā)生這種情況;因此,盡管存在“敵對”或不完整的源流,但 readObjectNoData 對于正確初始化反序列化對象很有用。

在將對象寫入流時需要指定要使用的替代對象的可序列化類應使用精確簽名實現(xiàn)此特殊方法:

 ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException; 

如果該方法存在并且可以從被序列化對象的類中定義的方法訪問,則該 writeReplace 方法由序列化調用。 因此,該方法可以具有私有、受保護和包私有訪問。 對該方法的子類訪問遵循 java 可訪問性規(guī)則。

當從流中讀取實例時需要指定替換的類應該使用精確的簽名實現(xiàn)這個特殊方法。

 ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException; 

此 readResolve 方法遵循與 writeReplace 相同的調用規(guī)則和可訪問性規(guī)則。

序列化運行時將版本號與每個可序列化類相關聯(lián),稱為 serialVersionUID,在反序列化期間使用該版本號來驗證序列化對象的發(fā)送者和接收者是否已為該對象加載了與序列化兼容的類。 如果接收者為對象加載了一個類,該對象的 serialVersionUID 與相應發(fā)送者的類不同,則反序列化將導致 InvalidClassException。 可序列化的類可以通過聲明一個名為“serialVersionUID”的字段來顯式聲明自己的serialVersionUID,該字段必須是靜態(tài)的、最終的和long類型:

 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; 

如果可序列化類沒有顯式聲明 serialVersionUID,則序列化運行時將根據類的各個方面為該類計算默認的 serialVersionUID 值,如 Java(TM) 對象序列化規(guī)范中所述。但是,強烈建議所有可序列化的類都顯式聲明 serialVersionUID 值,因為默認的 serialVersionUID 計算對類細節(jié)高度敏感,這些細節(jié)可能因編譯器實現(xiàn)而異,因此可能在反序列化期間導致意外的 InvalidClassExceptions。因此,為了保證在不同的 java 編譯器實現(xiàn)中具有一致的 serialVersionUID 值,可序列化的類必須聲明一個顯式的 serialVersionUID 值。還強烈建議顯式 serialVersionUID 聲明盡可能使用 private 修飾符,因為此類聲明僅適用于立即聲明的類——serialVersionUID 字段不能用作繼承成員。數(shù)組類不能顯式聲明 serialVersionUID,因此它們始終具有默認計算值,但數(shù)組類無需匹配 serialVersionUID 值。

Since:

JDK1.1

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號