簡體   English   中英

是否有一種內置的方法來檢測序列化的java對象是否缺少字段?

[英]is there a built-in way to detect if a serialized java object is missing fields?

我正在對我的Serializable類進行兼容修改,即添加一些原始字段(boolean,long)。 我的類是服務器提供的數據的客戶端表示。

當我從文件加載類時,我需要能夠檢測加載的類是否由早期版本保存,即它缺少一些java在加載時設置為默認值的字段。 如果是這種情況,我的應用程序仍然可以工作,但是當客戶端具有網絡連接時,我想從服務器獲取新字段。

Java是否有任何內置方法來檢測是否加載了類缺少字段?

(我意識到我可以使用“版本”實例成員手動解決這個問題;我希望盡管Java內置了一些內容)

您可以覆蓋Serializable接口的readObject()方法,以自定義處理類的反序列化。

請注意, 強烈建議您在實現Serializable時包含serialVersionUID:

private static final long serialVersionUID = 1;

如果你沒有定義它,那么就可以從類的成員的Hash中創建一個...然后如果你以后添加的內容如你所描述的那樣,UID將不匹配,Java將不允許你重新加載舊數據。

來自Serializable文檔的更多信息: http//docs.oracle.com/javase/6/docs/api/java/io/Serializable.html


關於處理不間斷變化的更多信息:

如果實現之間存在重大變化,那么您應該只更改serialVersionUID ,這使得使用新代碼反序列化舊版本毫無意義

如果通過添加一些字段來修改具有非中斷更改的類,則不應更改serialVersionUID。 如果原始類沒有指定的serialVersionUID,則會自動為您生成一個,並且將在您的新實現中自動生成一個舊的實現不匹配的新實現。

當您嘗試使用serialVersionUID不匹配反序列化舊版本時,系統將拋出java.io.InvalidClassException。 帶有此異常的錯誤消息將告訴您舊的serialVersionUID是什么以及新的serialVersionUID是什么。

然后,您可以修改您的類,使其具有與舊版本匹配的顯式指定的serialVersionUID,允許您反序列化舊版本和新版本,而不會拋出異常。

然后,運行時將在反序列化舊版本實例時將任何新的基元成員設置為其默認值

如果要檢測是否已對該類的舊版本或新版本進行反序列化,則可以檢查在readObject()實現中不應為默認值的默認值。

這是一個例子:

// add a new private field to the modified class for tracking version:
private int myNewVersionFlag = 123;

// then in your readObject implementation:
private void readObject(java.io.ObjectInputStream stream)
     throws IOException, ClassNotFoundException {

    stream.defaultReadObject();

    if( this.myNewVersionFlag == 0 ) {
        // if we get here the object being deserialized must
        // be an old version, so now set sensible defaults 
        // for the new params or whatever...
    }

}

還有其他更復雜的方法,包括實現自己的ObjectInputStream子類,但總的來說,我發現簡單地擁有一個不應該為零的版本字段對於許多用例來說簡單而且足夠。

摘要

  • 如果您始終指定自己的serialVersionUID,則代碼更有效(它不必自動生成散列的代碼),您可以更好地顯式處理未來的類更改。

  • 您應該只更改此值,如果您的更改正在中斷,並且意味着無法對您的類的舊版本進行反序列化,因為該類的新功能無法進行合理的默認設置。

  • 如果您有自己的私有成員用於跟蹤版本號,則可以在readObject()中使用此成員,以便在需要時反序列化舊實例時向新變量插入合理的默認值。

最后,Java序列化規范中涵蓋了您想要了解的有關反序列化的所有信息(但不敢提出):

http://docs.oracle.com/javase/7/docs/platform/serialization/spec/serialTOC.html

是的,您可以執行readObject方法中描述的操作。 它不會檢測是否缺少類字段,但您可以檢查相關字段是否為空,這樣您就可以執行任何操作。

http://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM