JavaRush /Java Blog /Random-TW /為什麼在 Java 中的 Serialized 類別中使用 SerialVersionUID
0xFF
等級 9
Донецк

為什麼在 Java 中的 Serialized 類別中使用 SerialVersionUID

在 Random-TW 群組發布
Serialization對許多 Java 開發人員來說SerialVersionUID始終是個謎。我經常看到關於什麼是 的問題SerialVersionUID,或者如果我不在SerialVersionUID我的類別中聲明會發生什麼Serializable為什麼在 Java 中的 Serialized 類別中使用 SerialVersionUID - 1除了令人困惑和不經常使用之外,這個問題的另一個原因是 Eclipse IDE 缺少警告SerialVersionUID,例如:「Serialized 類別 Customer 沒有聲明long類型Serializable的static Final SerialVersionUID 欄位」long“)。在本文中,您不僅將了解 Java 的基礎知識,還將了解它對序列化和反序列化過程的影響。當您宣告一個類別(如透過實作令牌介面)時,Java 執行時間將使用預設序列化機制在磁碟上儲存該類別的實例,除非您將進程配置為使用Externalized 介面。在序列化期間,Java 執行時會為此類別建立一個版本號,以便稍後可以反序列化。在 Java 中,此版本號稱為. 如果在反序列化期間沒有匹配,則進程將退出並在「」流中出現異常,並且還將列印類別名稱和相應的. 解決此問題的快速解決方案是將其複製並定義為類別中的類型常數。在這篇文章中,我們將了解為什麼要在Java中使用以及如何使用JDK的serialver工具來產生這個ID。如果您是序列化新手,您也可以觀看Top 10 Java Serialization Interview Questions來評估您的知識並找到您理解中的差距以供進一步閱讀。與(並發)和(多線程)一樣,(序列化)是另一個值得閱讀多次的主題。 CustomerSerialVersionUIDSerialVersionUIDSerializablejava.io.SerializableSerialVersionUIDSerialVersionUIDInvalidClassExceptionmainjava.io.InvalidClassExceptionSerialVersionUIDSerialVersionUIDprivate static final longSerialVersionUIDConcurrencyMulti-threadingSerialization

為什麼在 Java 中使用 SerialVersionUID

正如我所說,當我們沒有在類別中定義值時,序列化機制將為我們做這件事SerialVersionUIDstatic final long這種機制對許多細節都很敏感,包括類別的字段、它們的存取修飾符、它實現的接口,甚至不同的編譯器實現;對類別的任何更改或使用不同的編譯器都可能產生不同的結果,SerialVersionUID這最終將導致阻止序列化資料被重新載入。依賴Java的序列化機制來產生這個id是有風險的,這就是為什麼在SerialVersionUID你的Serialized類別中明確定義它是一個好主意。我強烈建議閱讀 Java 經典著作 - Joshua Bloch 《Effective Java》,以了解 Java 序列化以及錯誤處理它們的問題。對了,JDK還提供了一個工具serialver,位於JAVA_HOME目錄的bin目錄下,在我的電腦上是C:\Program Files\Java\jdk1.6.0_26\bin\serialver.exe,可以用來產生對於舊課程。如果您對類別進行的變更破壞了序列化並且您的應用程式無法重新載入序列化實例,則這非常有用。您可以輕鬆地使用此實用程式來建立舊實例,然後透過將該欄位聲明為private static final long來明確使用它。順便說一句,出於效能和安全原因,強烈建議使用常規二進位格式進行序列化;同樣,「Effective Java」有幾個段落非常詳細地演示了常規格式的優點。 SerialVersionUIDSerialVersionUID SerialVersionUID

如何使用serialver JDK實用程式產生SerialVersionUID

您可以使用serialver來產生SerialVersionUID類別。這對於開發類特別有用;該實用程式SerialVersionUID以易於複製的格式傳回。您可以使用serialverJDK 實用程序,如範例所示:
$ 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作為GUI命令$ serialver –show,這將開啟一個檢查器serial version,該檢查器會取得完整的類別名稱並顯示它Serial version

概括

現在我們知道它是什麼SerialVersionUID以及為什麼在類別中聲明它很重要Serializable,是時候回顧一下與 Java SerialVersionUID 相關的一些重要事實了。
  1. SerialVersionUID用於指示序列化資料的版本。

  2. 當我們不在SerialVersionUID類別中聲明時,Java運行時會為我們做這件事,但是這個過程對類別的許多元資料敏感,包括欄位數量、欄位類型、欄位存取修飾符、類別中實作的介面等。您可以在Oracle 的序列化文件中找到確切的資訊。

  3. 建議將 SerialVersionUID 宣告為 private static final long 變數以避免預設機制。如果您忘記了這一點,某些 IDE(例如Eclipse)也會發出警告,例如:「Serialized 類別 Customer 未聲明 long 類型的靜態最終 SerialVersionUID 欄位。」。儘管您可以透過前往「視窗」>「首選項」>「Java」>「編譯器」>「錯誤/警告」>「潛在程式設計問題」來停用此警告,但我建議不要這樣做。只有不需要資料恢復的時候我才可以大意。這是這個錯誤在 Eclipse IDE 中的樣子,您所需要做的就是快速做出第一個決定。 為什麼在 Java 中的 Serialized 類別中使用 SerialVersionUID - 2

  4. 您也可以使用 JDK 中的 Serialver 實用程式為 Java 中的類別產生串行版本。該實用程式還有一個 GUI,在傳遞 - 參數時啟用show

  5. 序列化的最佳實踐是顯式聲明SerialVersionUID, 以避免反序列化出現任何問題,特別是當您使用依賴於序列化資料的客戶端-伺服器應用程式(例如 RMI)時。
這都是關於SerialVersionUIDJava 的。現在我們知道為什麼在課堂上正確聲明很重要SerialVersionUID。您可以感謝 IDE 的提醒,這可能會破壞您的類別的反序列化。如果您想了解有關序列化和相關概念的更多信息,您還可以查看這些精彩的文章。 原文在這裡
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION