HOWTO · Java

Java의 SerialVersionUID

이 자습서는 Java에서 SerialVersionUID를 사용하는 방법을 보여줍니다.

이 페이지의 내용

이 튜토리얼은 Java에서 SerialVersionUID를 사용하는 방법을 보여줍니다.

Java의 ‘SerialVersionUID’

SerialVersionUID는 직렬화에 사용됩니다. 직렬화는 개체를 바이트 스트림으로 변환하여 데이터를 저장하고 어딘가로 보내는 프로세스이고 역직렬화는 그 반대 프로세스입니다.

직렬화 프로세스 중에 Java 런타임은 버전 번호를 각 Serializable 클래스와 연결합니다. 그 번호는 SerialVersionUID라고 합니다.

SerialVersionUID는 직렬화된 데이터의 발신자와 수신자가 해당 데이터에 대한 클래스를 로드했으며 직렬화 측면에서 호환되는지 확인하는 데 사용됩니다.

예를 들어 수신자가 해당 발신자의 클래스와 다른 SerialVersionUID를 사용하여 개체에 대한 클래스를 로드한 경우 InvalidClassException이 발생합니다.

Serializable 클래스에 대한 SerialVersionUID를 선언할 수 있습니다. SerialVersionUIDStatic FinalLong 유형으로 선언됩니다.

구문을 참조하십시오.

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 계산은 필드뿐만 아니라 생성자, 구현 절 등과 같은 다른 측면을 기반으로 합니다. 즉, 이전 버전과의 호환성도 유지하는 SerialVersionUID를 명시적으로 선언해야 합니다.