語言

ISerializable 介面

定義

類別的序列化是由實作 Java 的類別所啟用。

[Android.Runtime.Register("java/io/Serializable", "", "Java.IO.ISerializableInvoker")]
public interface ISerializable : Android.Runtime.IJavaObject, IDisposable, Java.Interop.IJavaPeerable
[<Android.Runtime.Register("java/io/Serializable", "", "Java.IO.ISerializableInvoker")>]
type ISerializable = interface
    interface IJavaObject
    interface IDisposable
    interface IJavaPeerable
衍生
屬性
實作

備註

類別的序列化能力是由實作 java.io.Serializable 介面的類別所啟用。

<強烈>警告:不可信資料的反序列化本質上具有危險性,應避免。 不可信的資料應該被仔細驗證。 </強壯>

未實作此介面的類別,其狀態不會被序列化或反序列化。 所有可序列化類別的子類型本身都是可序列化的。 序列化介面沒有方法或欄位,僅用來辨識可序列化的語意。

為了允許不可序列化類別的子型態被序列化,子型別可能會負責儲存並還原超型態的公用、保護及(若可存取)套件欄位的狀態。 子型只有在被延伸的類別擁有可存取的無 arg 建構子來初始化類別狀態時,才可承擔此責任。 若不符合序列化,宣告類別為可序列化(Serializable)則是錯誤。 錯誤會在執行時被偵測到。

在反序列化過程中,非序列化類別的欄位會使用該類別的公開或受保護的無 arg 建構器初始化。 無 arg 建構子必須能被可序列化的子類存取。 可序列化子類別的欄位會從串流中還原。

在遍歷圖時,可能會遇到不支援序列化介面的物件。 此時會拋出 NotSerializableException,並識別非序列化物件的類別。

在序列化與反序列化過程中需要特殊處理的類別,必須實作具有以下精確簽名的特殊方法:

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 方法負責為特定類別撰寫物件的狀態,以便對應的 readObject 方法能還原該物件。 儲存物件欄位的預設機制可以透過呼叫 .defaultWriteObject 來啟動。 此方法不必關注其超類或子類所屬的狀態。 狀態可透過使用 writeObject 方法寫入 ObjectOutputStream,或使用 DataOutput 支援的原始資料型別方法來儲存。

readObject 方法負責從串流讀取並還原類別欄位。 它可能會呼叫 in.defaultReadObject 來調用預設機制,還原物件的非靜態與非瞬態欄位。 defaultReadObject 方法利用串流中的資訊,將串流中儲存的物件欄位與當前物件中相應命名的欄位分配。 這適用於類別演化後新增欄位的情況。 此方法不必關注其超類或子類所屬的狀態。 狀態是透過從 ObjectInputStream 讀取各欄位的資料,並將該物件的適當欄位指派來恢復。 DataInput 支援讀取原始資料型別。

readObjectNoData 方法負責在序列化串流未將該類別列為被反序列化物件的超類別時,初始化物件的狀態。 這種情況可能發生在接收方使用與發送方不同版本的反序列實例類別,而接收方版本擴展了未被發送方版本擴充的類別。 這種情況也可能發生在序列化串流被竄改時;因此,readObjectNoData 對於在原始碼串流「敵對」或不完整的情況下,正確初始化反序列化物件非常有用。

需要指定替代物件以寫入串流的可序列化類別,應實作此特殊方法,並具備精確的簽名:

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

如果序列化有該方法存在,且可從被序列化物件類別中定義的方法存取,則會呼叫此 writeReplace 方法。 因此,該方法可以擁有私有、受保護及套件私密的存取權限。 此方法的子類別存取遵循 Java 無障礙規則。

需要在從串流讀取該實例時指定替換的類別,應實作此特殊方法並帶有精確的簽名。

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

此 readResolve 方法遵循與 writeReplace 相同的調用規則與可存取性規則。

序列化執行時會為每個可序列化類別關聯一個版本號,稱為 serialVersionUID,用於反序列化時驗證序列化物件的發送者與接收者是否已載入該物件的類別,且在序列化方面相容。 如果接收端載入的物件類別的序列版本UID與對應發送者類別的序列版本UID不同,則反序列化將導致 InvalidClassException。 可序列化類別可明確宣告自己的 serialVersionUID,方法是宣告一個必須 "serialVersionUID" 為靜態、最終且型別 long為 的欄位:

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

若可序列化類別未明確宣告 serialVersionUID,序列化執行時會根據類別的各種面向計算該類別的預設 serialVersionUID 值,詳見 Java(TM) 物件序列化規範。 然而,<>強烈建議<所有>可序列化類別明確宣告 serialVersionUID 值,因為預設的 serialVersionUID 計算對類別細節高度敏感,且這些細節會因編譯器實作而異,可能導致反序列化時出現意外InvalidClassException的 s。 因此,為了保證不同 Java 編譯器實作間 serialVersionUID 值一致,序列化類別必須宣告明確的 serialVersionUID 值。 同時強烈建議明確的 serialVersionUID 宣告盡可能使用 private 修飾符,因為此類宣告僅適用於立即宣告的類別——serialVersionUID 欄位作為繼承成員並不有用。 陣列類別無法明確宣告 serialVersionUID,因此它們總是預設計算值,但陣列類別則免除必須匹配 serialVersionUID 值的要求。

如果你針對 Android N,某些類別的 serialVersionUID 計算實作會有些微變動。為了維持相容性,只有當應用程式目標 SDK 版本設定為 24 或以上時,才會啟用此變更。 強烈建議使用明確的 serialVersionUID 欄位以避免相容性問題。

<h3>Implement Serializable Judiciously</h3> 請參閱 Effective Java 關於序列化的章節,以獲得序列化 API 的全面介紹。 書中說明如何在不損害應用程式維護性的情況下使用此介面。

<h3>推薦替代方案</h3><強>JSON/<strong> 簡潔、易讀且高效。 Android 內建 a android.util.JsonReader streaming API 和 a org.json.JSONObject tree API 來讀寫 JSON。 使用像 GSON 這樣的綁定函式庫直接讀寫 Java 物件。

在 1.1 版本中加入。

Java 文件 java.io.Serializable。

本頁部分內容為基於 Open Source Project 所創建與分享的作品,並依授權條款所描述的使用進行修改。

屬性

名稱 Description
Handle

取得底層 Android 物件的 JNI 值。

(繼承來源 IJavaObject)
JniIdentityHashCode

回傳包裹實例的 java.lang.System.identityHashCode() 值。

(繼承來源 IJavaPeerable)
JniManagedPeerState

管理貴族的狀況。

(繼承來源 IJavaPeerable)
JniObjectReferenceControlBlock

類別的序列化是由實作 Java 的類別所啟用。

(繼承來源 IJavaPeerable)
JniPeerMembers

成員存取與召喚支援。

(繼承來源 IJavaPeerable)
PeerReference

回傳JniObjectReference包裹後的 Java 物件實例。

(繼承來源 IJavaPeerable)

方法

名稱 Description
Disposed()

當實例被處理後才被召喚。

(繼承來源 IJavaPeerable)
DisposeUnlessReferenced()

如果沒有未解決的參考資料,則 Dispose()呼叫;否則,則不做任何事。

(繼承來源 IJavaPeerable)
Finalized()

當實例完成後才會被通知。

(繼承來源 IJavaPeerable)
SetJniIdentityHashCode(Int32)

將回傳的值設為 JniIdentityHashCode。

(繼承來源 IJavaPeerable)
SetJniManagedPeerState(JniManagedPeerStates)

類別的序列化是由實作 Java 的類別所啟用。

(繼承來源 IJavaPeerable)
SetPeerReference(JniObjectReference)

將回傳的值設為 PeerReference。

(繼承來源 IJavaPeerable)
UnregisterFromRuntime()

取消註冊此實例,讓執行時不會在未來 Java.Interop.JniRuntime+JniValueManager.PeekValue 的呼叫中回傳該實例。

(繼承來源 IJavaPeerable)

擴充方法

名稱 Description
GetJniTypeName(IJavaPeerable)

取得實例 self類型的 JNI 名稱。

JavaAs<TResult>(IJavaPeerable)

試著強制self輸入 TResult,檢查 強制在 Java 端是否有效。

JavaCast<TResult>(IJavaObject)

執行 Android 執行時間檢查的類型轉換。

JavaCast<TResult>(IJavaObject)

類別的序列化是由實作 Java 的類別所啟用。

TryJavaCast<TResult>(IJavaPeerable, TResult)

試著強制self輸入 TResult,檢查 強制在 Java 端是否有效。

適用於