序列化和反序列化的概念_序列化的概念
序列化和反序列化的概念
討論了為什么Optional不可序列化以及如何處理(即將推出)之后,讓我們仔細看看序列化。
總覽
這篇文章介紹了序列化的一些關鍵概念。 它嘗試精簡地執行此操作,而不會涉及太多細節,包括將建議降至最低。 它沒有敘述,更類似于Wiki文章。 主要信息來源是約書亞·布洛赫(Joshua Bloch)的出色著作《 有效的Java》 ,其中涉及到序列化的多個內容(第一版:54-57;第二版: 74-78 )。 在官方序列化規范中可以找到更多信息的方式
定義
通過序列化,實例可以被編碼為字節流(稱為序列化 ),并且這樣的字節流可以被轉換回實例(稱為反序列化 )。
關鍵功能是兩個進程不必由同一JVM執行。 這使得序列化成為一種在系統運行之間將對象存儲在磁盤上或在不同系統之間傳輸它們以進行遠程通信的機制。
語言外特征
序列化是一種有些奇怪的機制。 它將實例轉換為字節流,反之亦然,與類的交互很少。 它既不調用訪問器來獲取值,也不使用構造函數創建實例。 為此,該類的所有開發人員所需要做的就是實現一個沒有方法的接口。
Bloch將其描述為一種語言學特征 ,它是序列化中許多問題的根源。
方法
可以通過實現以下某些方法來自定義序列化過程。 它們可以是私有的,JVM將根據其簽名來找到它們。 這些描述摘自Serializable的類注釋 。
- private void writeObject(java.io.ObjectOutputStream out) throws IOException
負責為其特定類編寫對象的狀態,以便相應的readObject方法可以還原它。 - private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
負責從流中讀取并還原類字段。 - private void readObjectNoData() throws ObjectStreamException
在序列化流未將給定類列出為要反序列化的對象的超類的情況下,負責為其特定類初始化對象的狀態。 - ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException
指定將此類的對象寫入流時要使用的替代對象。 - ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
從流中讀取此類的實例時,指定一個替換對象。
處理反序列化的語言外特性的一種好方法是將所有涉及的方法視為該類的附加構造函數。
(反)序列化涉及的對象流提供了以下有用的默認(反)序列化方法:
- java.io.ObjectOutputStream.defaultWriteObject() throws IOException
將當前類的非靜態和非瞬態字段寫入此流。 - java.io.ObjectInputStream.defaultReadObject() throws IOException, ClassNotFoundException
從此流中讀取當前類的非靜態和非瞬態字段。
不變量
不使用構造函數創建實例的一種效果是,在反序列化時不會自動建立類的不變式。 因此,盡管類通常會檢查所有構造函數參數的有效性,但該機制不會自動應用于字段的反序列化值。
進行反序列化檢查是一項額外的工作,很容易導致代碼重復及其通常會引起的所有問題。 如果忘記或粗心地做,該類將打開漏洞或安全漏洞。
序列化表格
由infocux Technologies在CC-BY-NC 2.0下發布 。
可序列化類的字節流編碼的結構稱為其序列化形式 。 它主要由類字段的名稱和類型定義。
序列化的表單具有一些不立即可見的屬性。 盡管可以通過仔細定義表格來緩解某些有問題的問題,但它們通常仍然是班級未來發展的負擔。
公開API
序列化表格的最重要屬性是:
它是該類的公共API的一部分!
從部署可序列化類的那一刻起,必須假定已存在序列化實例。 通常期望系統支持使用同一系統的較早版本創建的實例的反序列化。 類的用戶依賴于其序列化形式以及其記錄的行為。
減少信息隱藏
信息隱藏的概念允許類在更改其實現方式的同時保留其記錄的行為。 這包括其狀態的表示,通常是隱藏的,可以根據需要進行調整。 由于捕獲狀態表示形式的序列化形式成為公共API的一部分,因此表示形式本身也是如此。
Serializable類只有有效地隱藏其行為的實施,同時暴露出該行為的界定和國家使用它來實現它。
靈活性降低
因此,就像更改類的API(例如,通過更改或刪除方法或更改其記錄的行為)一樣,使用它可能會破壞代碼,更改序列化形式也是如此。 不難發現,如果固定領域,提高班級就變得更加困難。 如果需要,這大大降低了更改此類的靈活性。
在JDK可序列化中進行處理會使我們的維護成本急劇增加,因為這意味著該表示將一直凍結。 這限制了我們將來開發實現的能力,而我們無法輕松修復錯誤或提供增強功能的情況數量非常之多,而這種情況本來就很簡單。 因此,盡管對您來說,這看起來像是一個“可序列化的實現”的簡單問題,但不僅限于此。 解決早期的選擇以使某些東西可序列化所消耗的工作量是驚人的。 布賴恩·格茨
增加測試工作量
如果更改了可序列化的類,則必須測試序列化和反序列化是否可以在系統的不同版本中工作。 這不是一件容易的事,并且會產生可衡量的成本。
類表示
from的序列化表示一個類,但并非所有表示都相等。
物理
如果一個類使用引用類型(即非基本類型)定義字段,則其實例包含指向這些類型的實例的指針。 這些實例又可以指向其他實例,依此類推。 這定義了互連實例的有向圖。 實例的物理表示形式是從該實例可到達的所有實例的圖形。
例如,考慮一個雙向鏈表。 列表中的每個元素都包含在一個節點中,并且每個節點都知道上一個和下一個。 這基本上已經是列表的物理表示形式。 包含一打元素的列表將是13個節點的圖形。 列表實例指向第一個列表節點和最后一個列表節點,從那里可以在兩個方向之間遍歷這十個節點。
序列化類實例的一種方法是簡單地遍歷圖并序列化每個實例。 這有效地將物理表示形式寫入字節流,這是默認的序列化機制。
雖然類的物理表示形式通常是實現細節,但是以這種方式對其進行序列化會暴露此隱藏信息。 序列化物理表示有效地將類綁定到該類,這使得將來很難更改它。 還有其他缺點,在有效Java (第2版的第297頁)中進行了介紹。
邏輯上
類狀態的邏輯表示通常更抽象。 通常從實施細節中將其刪除,并且包含的??信息較少。 在嘗試表達此表示形式時,建議將兩個方面都推到最大。 它應該盡可能地獨立于實現,并且從某種意義上講應該是最小的,因為遺漏了任何信息使得無法從中重新創建實例。
繼續鏈接列表的示例,請考慮鏈接列表的實際含義:僅按特定順序排列一些元素。 這些是否包含在節點中以及這些假想的節點如何鏈接都無關緊要。 因此,最小的邏輯表示將僅由那些元素組成。 (為了從流中正確地重新創建實例,有必要添加元素的數量。雖然這是多余的信息,但似乎并沒有太大的傷害。)
因此,良好的邏輯表示形式只能捕獲狀態的抽象結構,而不能捕獲表示狀態的具體字段。 這意味著盡管改變前者仍然存在問題,但后者可以自由發展。 與序列化物理表示相比,這為類的進一步開發恢復了很大一部分靈活性。
序列化模式
至少有三種方法可以序列化一個類。 稱呼所有這些模式都有些過頭,因此該術語被寬松地使用。
默認序列化表格
這就像在聲明中添加implements Serializable一樣簡單。 然后,序列化機制會將所有非臨時字段寫入流,并在反序列化時將流中存在的所有值分配給它們的匹配字段。
這是序列化類的最直接的方法。 這也是序列化所有尖銳的邊緣都變得平淡無奇,并等待它們轉而真正傷害您的地方。 序列化的形式捕獲物理表示,并且絕對不檢查不變量。
自定義序列化表格
通過實現writeObject一個類可以定義將哪些內容寫入字節流。 匹配的readObject必須讀取相應的流,并使用該信息將值分配給字段。
這種方法比默認形式具有更大的靈活性,可用于序列化類的邏輯表示。 有一些細節需要考慮,我只能建議閱讀Effective Java中的相應項目(第1版中的項目55;第2版中的項目75)。
序列化代理模式
在這種情況下,要序列化的實例將替換為代理。 該代理是從字節流而不是原始實例寫入和讀取的。 這可以通過實現方法writeReplace和readResolve來實現。
在大多數情況下,這是迄今為止最好的序列化方法。 它值得自己的職位 ,它會很快得到它( 住宿 調整 )。
雜項
有關序列化的其他一些細節。
人工字節流
反序列化的快樂路徑假定一個字節流是通過序列化同一類的實例創建的。 盡管在大多數情況下這樣做是可以的,但是在安全關鍵代碼中必須避免這樣做。 這包括任何使用序列化進行遠程通信的公共可訪問服務。
取而代之的是,必須假設攻擊者精心制作了流,以違反類的不變式。 如果不解決此問題,則可能導致系統不穩定,從而可能崩潰,破壞數據或受到攻擊。
文獻資料
Javadoc具有特殊的注釋,用于記錄類的序列化形式。 為此,它在文檔中創建了一個特殊頁面,其中列出了以下信息:
- 標記@serialData可以注釋方法,下面的注釋應該用來記錄字節流中寫入的數據。 方法簽名和注釋顯示在“ 序列化方法”下 。
- 標記@serial可以注釋字段,下面的注釋應該描述字段。 然后,該字段的類型和名稱以及注釋會在“ 序列化字段”下列出 。
一個很好的例子是LinkedList的文檔 。
翻譯自: https://www.javacodegeeks.com/2015/01/concepts-of-serialization.html
序列化和反序列化的概念
總結
以上是生活随笔為你收集整理的序列化和反序列化的概念_序列化的概念的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑截屏你都用什么键台式电脑如何截屏快捷
- 下一篇: 电脑用这个工具电脑使用工具