<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # Java `serialVersionUID` – 如何生成`serialVersionUID` > 原文: [https://howtodoinjava.com/java/serialization/serialversionuid/](https://howtodoinjava.com/java/serialization/serialversionuid/) **Java 序列化**是將對象轉換為字節流的過程,因此我們可以執行類似的操作,例如將其存儲在磁盤上或通過網絡發送。 反序列化是相反的過程 – 將字節流轉換為內存中的對象。 在序列化期間,java 運行時將版本號與每個可序列化的類相關聯。 稱為`serialVersionUID`的數字,在反序列化期間用于驗證序列化對象的發送者和接收者是否已加載了該對象的與序列化兼容的類。 如果接收者為對象加載的類`serialVersionUID`與相應發送者的類不同,則反序列化將導致`InvalidClassException`。 ## 1\. Java `serialVersionUID`語法 可序列化的類可以通過聲明一個名為“`serialVersionUID`”的字段來顯式聲明其自己的`serialVersionUID`,該字段必須是靜態的,最終的且類型為`long`。 ```java private static final long serialVersionUID = 4L; ``` 在這里,`serialVersionUID`表示類的版本,如果您對類的當前版本進行了修改,以使其不再與先前的版本向后兼容,則應該對它進行遞增。 ![Serialization-deserialization-demo](https://img.kancloud.cn/0c/bb/0cbb81bdd827a9faf41845b59a1a46a0_600x268.png) ## 2\. Java 序列化和反序列化示例 讓我們看一個如何將類序列化然后反序列化的示例。 ```java package com.howtodoinjava.demo.serialization; import java.io.*; import java.util.logging.Logger; public class DemoClass implements java.io.Serializable { private static final long serialVersionUID = 4L; //Default serial version uid private static final String fileName = "DemoClassBytes.ser"; //Any random name private static final Logger logger = Logger.getLogger(""); //Few data fields //Able to serialize private static String staticVariable; private int intVariable; //Not able to serialize transient private String transientVariable = "this is a transient instance field"; private Thread threadClass; public static void main(String[] args) throws IOException, ClassNotFoundException { //Serialization DemoClass test = new DemoClass(); test.intVariable = 1; staticVariable = "this is a static variable"; writeOut(test); System.out.println("DemoClass to be saved: " + test); //De-serialization System.out.println("DemoClass deserialized: " + readIn()); } private static Object readIn() throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File(fileName))); return ois.readObject(); } private static void writeOut(java.io.Serializable obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File(fileName))); oos.writeObject(obj); oos.close(); } @Override public String toString() { return "DemoClass: final static fileName=" + fileName + ", final static logger=" + logger + ", non-final static staticVariable=" + staticVariable + ", instance intVariable=" + intVariable + ", transient instance transientVariable=" + transientVariable + ", non-serializable instance field threadClass:=" + threadClass; } } ``` 程序輸出。 ```java DemoClass to be saved: DemoClass: final static fileName=DemoClassBytes.ser, final static logger=java.util.logging.LogManager$RootLogger@1d99a4d, non-final static staticVariable=this is a static variable, instance intVariable=1, transient instance transientVariable=this is a transient instance field, non-serializable instance field threadClass:=null //Execute readIn() function from a separate main() method //to get given below output correctly. It will flush out the static fields. DemoClass deserialized: DemoClass: final static fileName=DemoClassBytes.ser, final static logger=java.util.logging.LogManager$RootLogger@cd2c3c, non-final static staticVariable=null, instance intVariable=1, transient instance transientVariable=null, non-serializable instance field threadClass:=null ``` > 如果可序列化的類未顯式聲明`serialVersionUID`,則序列化運行時將根據該類的各個方面計算該類的默認`serialVersionUID`值。 ## 3\. 如何生成`serialVersionUID` Joshua Bloch 在《Effective Java》中說,自動生成的 UID 是基于類名稱,已實現的接口以及所有公共和受保護成員生成的。 以任何方式更改其中任何一個都將更改`serialVersionUID`。 但是,強烈建議所有可序列化的類顯式聲明`serialVersionUID`值,因為默認的`serialVersionUID`計算對類詳細信息高度敏感,類詳細信息可能會根據編譯器的實現而有所不同,并且可以在不同的環境中產生不同的`serialVersionUID`。 這可能導致反序列化期間出現意外的[**`InvalidClassException`**](https://docs.oracle.com/javase/10/docs/api/java/io/InvalidClassException.html "InvalidClassException")。 因此,為了在不同的 Java 編譯器實現中保證一致的`serialVersionUID`值,可序列化的類必須聲明一個顯式的`serialVersionUID`值。 強烈建議在可能的情況下,顯式`serialVersionUID`聲明在`serialVersionUID`中使用`private`修飾符,因為此類聲明僅適用于立即聲明的類。 另請注意,`serialVersionUID`字段不能用作繼承成員。 基于我的短暫職業,我可以說長時間存儲序列化數據(***空間序列化***)并不是很常見的用例。 使用序列化機制將數據臨時寫入(***時間序列化***)到例如高速緩存,或通過網絡將其發送到另一個程序以利用信息,這是更為常見的。 在這種情況下,我們對保持向后兼容性不感興趣。 我們只關心確保在網絡上通信的代碼庫確實具有相同版本的相關類。 為了方便進行此類檢查,我們必須保持`serialVersionUID`不變,并且不要對其進行更改。 另外,在網絡上的兩個應用程序上對類進行不兼容的更改時,請不要忘記更新它。 ## 4\. 沒有`serialVersionUID`的 Java 類 這不是我們永遠想要面對的情況。 但是,這是現實,有時甚至會發生(我應該很少說嗎?)。 如果我們需要以不兼容的方式更改此類,但又想使用該類的舊版本維護序列化/反序列化特性,則可以**使用 JDK 工具“[serialver](https://docs.oracle.com/javase/7/docs/technotes/tools/solaris/serialver.html "serialver command")”。 該工具在舊類**上生成`serialVersionUID`,并在新類上顯式設置它。 不要忘記實現`readObject()`和`writeObject()`方法,因為內置的反序列化機制(`in.defaultReadObject()`)將拒絕從舊版本的數據中反序列化。 如果我們定義自己的`readObject()`函數,可以讀取回舊數據。 此自定義代碼應檢查`serialVersionUID`,以便了解數據所在的版本并決定如何對其進行反序列化。 如果我們存儲可以在您的代碼的多個版本中保留的序列化數據,則此版本控制技術很有用。 > 閱讀更多: [Java 序列化兼容和不兼容的更改](https://howtodoinjava.com/java/serialization/a-mini-guide-for-implementing-serializable-interface-in-java/) ## 5\. Java `serialVersionUID`– 總結 1. `transient`和`static`字段在序列化中被忽略。 反序列化之后,`transient`字段和非最終靜態字段將為`null`。 `final`和`static`字段仍具有值,因為它們是類數據的一部分。 2. `ObjectOutputStream.writeObject(obj)`和`ObjectInputStream.readObject()`用于序列化和反序列化。 3. 在序列化期間,我們需要處理`IOException`; 在反序列化期間,我們需要處理`IOException`和`ClassNotFoundException`。 因此,反序列化的類類型必須在類路徑中。 4. 允許使用未初始化的,不可序列化的,非瞬態的實例字段。 添加“ `private Thread th;`”時,`Serializable`沒有錯誤。 但是,“`private Thread threadClass = new Thread();`”將導致異常: ```java Exception in thread "main" java.io.NotSerializableException: java.lang.Thread at java.io.ObjectOutputStream.writeObject0(Unknown Source) at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source) at java.io.ObjectOutputStream.writeSerialData(Unknown Source) at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source) at java.io.ObjectOutputStream.writeObject0(Unknown Source) at java.io.ObjectOutputStream.writeObject(Unknown Source) at com.howtodoinjava.demo.serialization.DemoClass.writeOut(DemoClass.java:42) at com.howtodoinjava.demo.serialization.DemoClass.main(DemoClass.java:27) ``` 5. 序列化和反序列化可用于復制和克隆對象。 它比常規克隆慢,但是[**可以很容易地產生深拷貝**](//howtodoinjava.com/java/serialization/how-to-do-deep-cloning-using-in-memory-serialization-in-java/ "How to do deep cloning using in memory serialization in java") 。 6. 如果我需要序列化`Serializable`類`Employee`,但是其超類之一不是可序列化的,`Employee`類是否仍可以序列化和反序列化? 答案是肯定的,前提是不可序列化的超類具有無參構造器,在反序列化時調用該構造器以初始化該超類。 7. 我們在修改實現`java.io.Serializable`的類時必須小心。 如果類不包含`serialVersionUID`字段,則其`serialVersionUID`將由編譯器自動生成。 不同的編譯器或同一編譯器的不同版本將生成潛在的不同值。 8. `serialVersionUID`的計算不僅基于字段,而且還基于類的其他方面,例如`Implement`子句,構造器等。因此,最佳實踐是顯式聲明`serialVersionUID`字段以保持向后兼容性。 如果我們需要實質性地修改可序列化的類,并希望它與以前的版本不兼容,則需要增加`serialVersionUID`以避免混合使用不同的版本。 學習愉快!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看