搜尋
首頁Javajava教程Java中物件序列化與反序列化詳解

本文實例講述了Java中物件序列化與反序列化。分享給大家供大家參考。具體如下:

一、簡介

物件序列化(Serializable)是指將物件轉換為位元組序列的過程,而反序列化則是根據位元組序列恢復物件的過程。

序列化一般用於以下場景:

1.永久性保存對象,保存對象的位元組序列到本地文件中;
2.透過序列化對像在網路中傳遞對象;
3.透過序列化在進程間傳遞對象。

物件所屬的類別必須實作Serializable或是Externalizable介面才能被序列化。對實現了Serializable接口的類,其序列化與反序列化採用預設的序列化方式,Externalizable接口是繼承了Serializable接口的接口,是對Serializable的擴展,實現了Externalizable接口的類完全自己控制序列化與反序列化行為。

Java.io.ObjectOutputStream代表物件輸出流,其方法writeObject(Object obj)可以實現物件的序列化,將得到的位元組序列寫入目標輸出流。

Java.io.ObjectInputStream代表物件輸入流,其readObject()方法能從來源輸入流中讀取位元組序列,將其反序列化為對象,並將其傳回。

二、序列化的幾種方式

假設定義了一個Customer類,根據Customer實現序列化方式的不同,可能有以下幾種序列化方式:

1.實作Serializable,未定義readObject和writeObject方法

ObjectOutputStream使用JDK預設方式對Customer物件的非transient的實例變數進行序列化;
ObjectInputStream使用JDK預設方式對Customer物件的非transient的實例變數進行反序列化。

2.實作Serializable,並定義了readObject和writeObject方法

ObjectOutputStream呼叫Customer類別的writeObject(ObjectOutputStream out)方法對Customer物件的非transient的實例變數進行序列化;
ObjectInputStreamStreamAustomerStream inputStream版本的調用(CustomerStream inObject(CustomerStreamInputStream)。 )方法對Customer物件的非transient的實例變數進行反序列化。

3.實作Externalizable,定義readExternal和writeExternal方法

ObjectOutputStream呼叫Customer類別的writeExternal方法對Customer物件的非transient實例變數進行序列化;
ObjectInputStream首先透過Customer物件類別的無物件函數進行一個序列化;用readExternal方法對Customer物件的非transient實例變數進行反序列化。

三、Serializable介面

類別透過實作 java.io.Serializable 介面以啟用其序列化功能。未實作此介面的類別將無法使其任何狀態序列化或反序列化。可序列化類別的所有子類型本身都是可序列化的。序列化介面沒有方法或字段,僅用於標識可序列化的語義。

在反序列化過程中,將使用該類別的公用或受保護的無參數建構方法初始化不可序列化類別的欄位。可序列化的子類別必須能夠存取無參數構造方法。可序列化子類別的欄位將從該流中恢復。

當遍歷一個類別視圖時,可能會遇到不支援 Serializable 介面的物件。在此情況下,將拋出 NotSerializableException,並將標識不可序列化物件的類別。

1.準確簽名

在序列化和反序列化過程中需要特殊處理的類別必須使用下列準確簽名來實現特殊方法:

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 方法負責寫入特定類別的物件的狀態,以便將它還原為對應的。透過呼叫 out.defaultWriteObject 可以呼叫保存 Object 的欄位的預設機制。該方法本身不需要涉及屬於其超類別或子類別的狀態。透過使用 writeObject 方法或使用 DataOutput 支援的用於基本資料類型的方法將各個欄位寫入 ObjectOutputStream,狀態可以被保存。

readObject 方法負責從流中讀取並還原類別欄位。它可以呼叫 in.defaultReadObject 來呼叫預設機制,以還原物件的非靜態和非瞬態欄位。 defaultReadObject 方法使用流中的資訊來指派流中透過目前物件中對應指定欄位所儲存的物件的欄位。這用於處理類別演化後需要新增欄位的情況。該方法本身不需要涉及屬於其超類別或子類別的狀態。透過使用 writeObject 方法或使用 DataOutput 支援的用於基本資料類型的方法將各個欄位寫入 ObjectOutputStream,狀態可以被保存。

在序列化流不列出給定類別作為將被反序列化物件的超類別的情況下,readObjectNoData 方法負責初始化特定類別的物件狀態。這在接收方使用的反序列化實例類別的版本不同於發送方,且接收者版本擴展的類別不是發送者版本擴展的類別時發生。在序列化流已經被篡改時也將發生;因此,不管源流是「敵意的」還是不完整的,readObjectNoData 方法都可以用來正確地初始化反序列化的物件。

將物件寫入流時需要指定要使用的替代物件的可序列化類,應使用準確的簽章來實作此特殊方法:

ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
此writeReplace方法將由序列化調用,前提是如果此方法存在,而且它可以透過被序列化物件的類別中定義的一個方法來存取。因此,此方法可以擁有私有 (private)、受保護的(protected) 和套件私有 (package-private) 存取。子類別對此方法的存取遵循 java 存取規則。

在從流中讀取類別的一個實例時需要指定替代的類別應使用的準確簽章來實作此特殊方法。

ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
此readResolve方法遵循與writeReplace相同的呼叫規則和存取規則。
如果一個類別定義了readResolve方法,那麼在反序列化的最後將呼叫readResolve方法,該方法傳回的物件為反序列化的最終結果。

2.serialVersionUID

序列化運行時使用一個稱為serialVersionUID 的版本號與每個可序列化類別相關聯,該序號在反序列化過程中用於驗證序列化物件的發送者和接收者是否為該物件載入了與序列化相容的類別。如果接收者載入的該物件的類別的 serialVersionUID 與對應的發送者的類別的版本號碼不同,則反序列化將會導致 InvalidClassException。可序列化類別可以透過宣告名為"serialVersionUID" 的欄位(此欄位必須是靜態(static)、最終(final) 的long 型欄位)明確宣告其自己的serialVersionUID:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果可序列化類別未明確聲明serialVersionUID,則序列化運行時將基於該類別的各個方面計算該類別的預設serialVersionUID 值,如“Java(TM) 物件序列化規範”中所述。不過,強烈建議所有可序列化類別都明確聲明serialVersionUID 值,原因是計算預設的serialVersionUID 對類別的詳細資訊具有較高的敏感性,根據編譯器實現的不同可能千差萬別,這樣在反序列化過程中可能會導致意外的InvalidClassException。因此,為確保 serialVersionUID 值跨不同 java 編譯器實現的一致性,序列化類別必須宣告一個明確的 serialVersionUID 值。也強烈建議使用 private 修飾符顯示聲明 serialVersionUID(如果可能),原因是這種聲明僅應用於直接聲明類別 -- serialVersionUID 欄位作為繼承成員沒有用處。陣列類別不能宣告一個明確的 serialVersionUID,因此它們總是具有預設的計算值,但是陣列類別沒有符合 serialVersionUID 值的要求。

3.Externalizable介面

Externalizable是Serailizable的擴展,實現Externalizable介面的類別其序列化有以下特點:
序列化時呼叫類別的方法writeExternal,反序列化呼叫readExternal方法;
序列化時呼叫類別的方法writeExternal,反序列化呼叫readExternal方法;

序列化時在執行反序列化時先呼叫類別的無參數建構函數,這點與預設的反序列化是不同的,因此對實作Externalizable介面來實現序列化的類別而言,必須提供一個public的無參數建構函數,否則在反序列化時將出現異常。

四、總結

如果採用預設的序列化方式,只要讓一個類別實現Serializable接口,其實例就可以被序列化。通常,專門為繼承而設計的類別應該盡量不要實作Serializable接口,因為一旦父類別實作了Serializable接口,其所有子類別也都是可序列化的了。

預設的序列化方式的不足之處:


1.直接對物件的不宜對外公開的敏感資料進行序列化,這是不安全的;
2.不會檢查物件的成員變數是否符合正確的約束條件,有可能被篡改資料而導致運行異常;
3.需要對物件圖做遞歸遍歷,如果物件圖很複雜,會消耗很多資源,設定引起Java虛擬機的堆疊溢出;

4.使類別的介面被類別的內部實作約束,制約類別的升級與維護。

透過實作Serializable介面的private類型的writeObject()和readObject(),或是實作Externalizable介面,並實作writeExternal()與readExternal()方法,並提供public型別的無參數構造函數兩種方式來控制序列化過程可以有效規避預設序列化方式的不足之處。

希望本文所述對大家的java程式設計有幫助。

更多Java中物件序列化與反序列化詳解相關文章請關注PHP中文網! 🎜
陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?Mar 17, 2025 pm 05:46 PM

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?Mar 17, 2025 pm 05:45 PM

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?Mar 17, 2025 pm 05:44 PM

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?Mar 17, 2025 pm 05:43 PM

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Mar 17, 2025 pm 05:35 PM

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。