爲什麼要在Java的Serializable類中使用SerialVersionUID

序列化和SerialVersionUID始終是許多Java開發人員的難題。 我經常會看到類似此SerialVersionUID的問題,或者如果不在我的Serializable類中聲明SerialVersionUID會發生什麼情況? 除了涉及到的複雜性和罕見的使用之外,這些問題的另一個原因是Eclipse IDE發出警告,警告不要缺少SerialVersionUID,例如「 Serializable類Customer不會聲明long類型的靜態最終SerialVersionUID字段」 在本文中,您不僅將學習Java SerialVersionUID的基礎知識,而且還將瞭解其在序列化和反序列化過程中的作用。 通過實現標記接口java.io.Serializable將一個類聲明爲Serializable時,如果您尚未使用Externalizable接口自定義該過程,則Java運行時將使用默認的Serialization機制將該類的實例持久化到磁盤中。 在序列化過程中,Java運行時會爲一個類創建一個版本號,以便以後可以反序列化它。 此版本號在Java中稱爲SerialVersionUID 如果在反序列化過程中,SerialVersionUID不匹配,則過程將失敗,並在線程「 main」 java.io.InvalidClassException中以InvalidClassException作爲Exception ,同時還會打印類名和相應的SerialVersionUID。 解決此問題的快速解決方案是複製SerialVersionUID並將其聲明爲類中的私有靜態最終長常量。 在本文中,我們將瞭解爲什麼要在Java中使用SerialVersionUID以及如何使用serialver JDK工具生成此ID。 如果您不熟悉序列化,還可以查看「 十大Java序列化面試」問題,以評估您的知識並找到理解上的空白以供進一步閱讀。 與併發和多線程類似,序列化是另一個主題,值得一讀。

就像我說的那樣,當我們不聲明SerialVersionUID作爲類中的靜態,最終值和長整型值時,序列化機制會爲我們創建它。 該機制對許多細節敏感,包括您的類中的字段,訪問修飾符,它們實現的接口,甚至不同的Compiler實現,對類的任何更改或使用不同的編譯器都可能導致產生不同的SerialVersionUID ,許多最終都會停止重新加載序列化的數據。 依靠Java序列化機制生成此id太冒險了,這就是爲什麼建議在Serializable類中聲明顯式SerialVersionUID的原因。 我強烈建議閱讀Joshua Bloch的經典Java標題「 Effective Java」,以瞭解Java序列化和不正確處理它的問題。 順便說一下,JDK還提供了一個名爲serialver的工具,位於我的機器C:\ Program Files \ Java \ jdk1.6.0_26 \ bin \ serialver.exe的JAVA_HOME文件夾的bin目錄中,該工具可用於爲舊版本生成SerialVersionUID類。 如果您在類中進行了更改(這會破壞序列化並且您的應用程序無法重新加載序列化的實例),這將非常有用。 您可以簡單地使用此工具爲舊實例創建SerialVersionUID,然後通過聲明一個privatestaticfinallong SerialVersionUID字段在類中顯式使用它。 順便說一句,出於性能和安全性的考慮,強烈建議您使用自定義二進制格式進行序列化,Effective Java再次提供了幾項,這詳細解釋了自定義格式的優點。

您可以使用JDK的serialver工具爲類生成SerialVersionUID。 這對於正在發展的類特別有用,它以易於複製的格式返回SerialVersionUID。 您可以使用serialver JDK工具,如以下示例所示:

$ serialver
use: serialver [-classpath classpath] [-show] [classname...]

$ serialver -classpath . Hello
Class Hello is not Serializable.

$ serialver -classpath . Hello
Hello:    static final long SerialVersionUID = -4862926644813433707L;

您甚至可以通過運行命令$ serialver -show以GUI形式使用serialver工具,這將打開串行版本檢查器,該檢查器將使用完整的類名並顯示其串行版本。

現在我們知道什麼是SerialVersionUID以及爲什麼在Serializable類中聲明它很重要,是時候修改一些與Java SerialVersionUID相關的重要事實了。

  1. SerialVersionUID用於對序列化數據進行版本控制。 如果類的SerialVersionUID與序列化的實例匹配,則只能反序列化該類。
  2. 當我們不在類中聲明SerialVersionUID時,Java運行時會爲我們生成它,但是該過程對許多類元數據敏感,包括字段數,字段類型,字段訪問修飾符,由類實現的接口等。您可以在Oracle的序列化文檔中找到準確的信息。
  3. 建議將SerialVersionUID聲明爲私有靜態最終長型變量,以避免使用默認機制。 如果您錯過了某些Eclipse之類的 IDE,也會顯示警告,例如「 Serializable類Customer不會聲明long類型的靜態最終SerialVersionUID字段」 儘管可以通過轉到窗口>首選項> Java>編譯器>錯誤/警告>潛在的編程問題來禁用此警告,但我建議不要這樣做。 唯一的情況是,在不需要恢復數據時,我會很粗心。 這是該錯誤在Eclipse IDE中的樣子,您需要做的就是接受第一個快速修復。
  4. 什麼是Java中的SerialVersionUID以及爲什麼需要它

  5. 您甚至可以使用JDK中的serialver工具爲Java中的類生成Serial Version。 它還具有一個GUI,可以通過傳遞-show參數來啓用它。
  6. 明確聲明SerialVersionUID是Java的序列化最佳實踐,以避免在反序列化期間出現任何問題,尤其是在運行依賴於序列化數據的客戶端服務器應用程序(例如RMI)的情況下。

這就是Java中的SerialVersionUID的全部內容。 現在我們知道了爲什麼在類中聲明SerialVersionUID很重要。 您可以感謝您的IDE的提醒,這可能會破壞您的類的反序列化。

如果您想了解有關序列化和相關概念的更多信息,還可以看到以下精彩文章:

翻譯自: https://www.javacodegeeks.com/2014/05/why-use-serialversionuid-inside-serializable-class-in-java.html