2013-10-03 25 views
0

我序列化一個對象,並通過網絡傳遞它。我的序列化的類對象有我自己定義的serilizableId。現在在另一個JVM中,我保持SeriliazibleId相同,但是改變了一些屬性。 會發生什麼,爲什麼?它能夠反序列化它嗎?SerializationVersionId相同,但類被修改?

+2

你試過了嗎? – Vulcan

+0

只是保持號碼相同將無法正常工作。寫入/讀取的數據需要保持一致。 –

回答

1

您必須參考Java對象序列化規範here

在具體的,你是什麼允許這樣做:

  • 刪除字段 - 如果某個字段在一個類中刪除,寫將不包含它的價值流。當流由較早的類讀取時,字段的值將被設置爲默認值,因爲流中沒有可用值。但是,此默認值可能會損害早期版本履行合同的能力。
  • 將層次向上或向下移動層次結構 - 由於流中的數據以錯誤的順序出現,因此這是不允許的。
  • 將非靜態字段更改爲靜態或非瞬態字段爲瞬態 - 依賴默認序列化時,此更改等同於從類中刪除字段。該版本的類不會將該數據寫入流中,因此該類的早期版本將無法讀取該數據。在刪除字段時,早期版本的字段將被初始化爲默認值,這可能導致類以意外的方式失敗。
  • 更改原始字段的聲明類型 - 類的每個版本都使用其聲明的類型寫入數據。試圖讀取字段的類的早期版本將失敗,因爲數據流中的數據類型與字段的類型不匹配。
  • 更改writeObject或readObject方法,以便它不再寫入或讀取默認字段數據或更改它,以便在以前版本沒有寫入或讀取它時嘗試寫入或讀取它。默認的字段數據必須始終顯示或不出現在流中。
  • 將類從Serializable更改爲Externalizable或反之亦然是不兼容的更改,因爲該流將包含與可用類的實現不兼容的數據。
  • 將類從非枚舉類型更改爲枚舉類型,反之亦然,因爲該流將包含與可用類的實現不兼容的數據。
  • 刪除Serializable或Externalizable是一個不兼容的更改,因爲它在寫入時將不再提供舊版本類所需的字段。
  • 如果行爲會產生與任何舊版本類型不兼容的對象,則將writeReplace或readResolve方法添加到類是不兼容的。

你被允許做什麼,而不是:

  • 添加字段 - 當被重組類具有不流中出現一個字段,在對象字段將被初始化爲其類型的默認值。如果需要類特定的初始化,則該類可以提供一個readObject方法,該方法可以將該字段初始化爲非默認值。
  • 添加類 - 流將包含流中每個對象的類型層次結構。比較流中的這個層次結構和當前類可以檢測到其他的類。由於初始化對象的流中沒有信息,因此該類的字段將被初始化爲默認值。
  • 刪除類 - 將流中的類層次與當前類的類層次進行比較可以檢測到某個類已被刪除。在這種情況下,將從流中讀取與該類對應的字段和對象。原始字段被丟棄,但刪除的類所引用的對象被創建,因爲它們可能在後面的流中被引用。當流被垃圾收集或重置時,它們將被垃圾收集。
  • 添加writeObject/readObject方法 - 如果讀取流的版本具有這些方法,那麼readObject與往常一樣需要讀取通過默認序列化寫入流的所需數據。它應該在讀取任何可選數據之前先調用defaultReadObject。 writeObject方法與往常一樣,可以調用defaultWriteObject來寫入所需的數據,然後寫入可選數據。
  • 刪除writeObject/readObject方法 - 如果讀取流的類沒有這些方法,則將通過默認序列化讀取所需的數據,並且可選數據將被丟棄。
  • 添加java.io.Serializable - 這相當於添加類型。這個類的流中將沒有值,所以它的字段將被初始化爲默認值。對非序列化類進行子類化的支持要求類的超類型具有無參數構造函數,並且類本身將被初始化爲默認值。如果無參數構造函數不可用,則拋出InvalidClassException。
  • 更改對字段的訪問 - 訪問修飾符public,package,protected和private對序列化向字段賦值的能力沒有影響。
  • 將字段從靜態變爲非靜態或瞬態變爲非瞬態 - 依靠默認序列化計算可序列化字段時,此更改等同於向類中添加字段。新字段將寫入流中,但較早的類將忽略該值,因爲序列化不會將值分配給靜態或瞬態字段。
0

如果您使用private static final long serialVersionUID;爲類,那麼你是確保任何版本的變化,直到它們是向後兼容的,將不會影響你的類反序列化。如果它不向後兼容,那麼你需要增加序列版本ID。

相關問題