Java の SerialVersionUID

Sheeraz Gul 2023年10月12日
Java の SerialVersionUID

このチュートリアルでは、Java で SerialVersionUID を使用する方法を示します。

Java の SerialVersionUID

SerialVersionUID はシリアル化に使用されます。 シリアライゼーションは、オブジェクトをバイト ストリームに変換してデータを保存し、どこかに送信するプロセスであり、デシリアライゼーションはその逆のプロセスです。

シリアル化プロセス中に、Java ランタイムは各 Serializable クラスにバージョン番号を関連付けます。 その番号は SerialVersionUID と呼ばれます。

SerialVersionUID は、シリアル化されたデータの送信者と受信者がそのデータのクラスをロードし、シリアル化に関して互換性があることを確認するために使用されます。

たとえば、受信側が、対応する送信側のクラスとは異なる SerialVersionUID を持つオブジェクトのクラスをロードした場合、InvalidClassException をスローします。

Serializable クラスに対して独自の SerialVersionUID を宣言できます。 SerialVersionUIDStatic Final および Long 型として宣言されます。

構文を参照してください。

private static final long serialVersionUID = 10L;

SerialVersionUID でシリアル化と逆シリアル化を実装する例を試してみましょう。 例を参照してください:

package delftstack;

import java.io.*;
import java.util.logging.Logger;

public class Example implements java.io.Serializable {
  // The Default serial version uid
  private static final long serialVersionUID = 4L;
  // random name
  private static final String File_Name = "ExampleClassBytes.ser";
  private static final Logger logger_File = Logger.getLogger("");
  // Few data fields Which will be able to serialize
  private static String Static_Variable;
  private int Integer_Variable;

  // Few data fields Which will not be able to serialize
  transient private String Transient_Variable = "this is a transient instance field";
  private Thread Thread_Class;

  private static Object readIn() throws IOException, ClassNotFoundException {
    ObjectInputStream Object_Input_Stream =
        new ObjectInputStream(new FileInputStream(new File(File_Name)));
    return Object_Input_Stream.readObject();
  }

  private static void writeOut(java.io.Serializable object) throws IOException {
    ObjectOutputStream Object_Output_Stream =
        new ObjectOutputStream(new FileOutputStream(new File(File_Name)));
    Object_Output_Stream.writeObject(object);
    Object_Output_Stream.close();
  }

  @Override
  public String toString() {
    return "Example Class:- final static fileName is: " + File_Name + ", final static logger is: "
        + logger_File + ", the non-final static staticVariable is: " + Static_Variable
        + ", the instance intVariable is: " + Integer_Variable
        + ", the transient instance Variable is: " + Transient_Variable
        + ", the non-serializable instance field threadClass is : " + Thread_Class;
  }

  public static void main(String[] args) throws IOException, ClassNotFoundException {
    // Serialization

    Example Demo = new Example();
    Demo.Integer_Variable = 1;
    Static_Variable = "this is the static variable";
    writeOut(Demo);
    System.out.println("Example Class to be saved: " + Demo);

    // De-serialization

    System.out.println("Example Class deserialized: " + readIn());
  }
}

Serializable クラスが明示的に SerialVersionUID を宣言しない場合、ランタイムはアスペクトに基づいてそのクラスのデフォルト SerialVersionUID を計算します。 上記のコードの出力を見てみましょう。

Example Class to be saved: Example Class:- final static fileName is: ExampleClassBytes.ser, final static logger is: java.util.logging.LogManager$RootLogger@27973e9b, the non-final static staticVariable is: this is the static variable, the instance intVariable is: 1, the transient instance Variable is: this is a transient instance field, the non-serializable instance field threadClass is : null
Example Class deserialized: Example Class:- final static fileName is: ExampleClassBytes.ser, final static logger is: java.util.logging.LogManager$RootLogger@27973e9b, the non-final static staticVariable is: this is the static variable, the instance intVariable is: 1, the transient instance Variable is: null, the non-serializable instance field threadClass is : null

上記のシナリオに基づく SerialVersionUID に関するいくつかの重要なポイント:

  1. 静的フィールドと一時フィールドはシリアル化中に無視され、逆シリアル化の後、一時フィールドと非静的最終フィールドは null になります。
  2. シリアル化には IOException を処理する必要があり、逆シリアル化には IOExceptionClassNotFoundException を処理する必要があります。 つまり、デシリアライズされたクラス タイプがクラス パスにある必要があります。
  3. メソッド ObjectInputStream.readObject() および ObjectOutputStream.writeObject(object) は、シリアライゼーションおよびデシリアライゼーション操作に使用されます。
  4. シリアライゼーションとデシリアライゼーションを使用してオブジェクトを複製およびコピーできますが、これは通常の複製操作よりも比較的低速です。
  5. 初期化されていない、シリアル化できない、一時的でないインスタンスは許容されます。
  6. java.io.Serializable を実装するクラスを変更するときは注意が必要です。クラスに SerialVersionUID が含まれていない場合、SerialVersionUID がコンパイラによって生成されるためです。
  7. SerialVersionUID の計算は、フィールドだけでなく、コンストラクター、implement 句などの他の側面にも基づいています。これは、下位互換性も維持する SerialVersionUID を明示的に宣言する必要があることを意味します。
著者: Sheeraz Gul
Sheeraz Gul avatar Sheeraz Gul avatar

Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.

LinkedIn Facebook