SerialVersionUID in Java

Sheeraz Gul Oct 12, 2023
SerialVersionUID in Java

This tutorial demonstrates how to use SerialVersionUID in Java.

SerialVersionUID in Java

The SerialVersionUID is used in serialization. Serialization is a process where we convert an object to a stream of bytes to store the data and send it somewhere, and deserialization is the reverse process.

During the serialization process, the Java runtime will associate a version number with each Serializable class; that number is called SerialVersionUID.

The SerialVersionUID is used to verify that the sender and receiver of the serialized data have loaded the classes for that data and are compatible in terms of serialization.

For example, if a receiver has loaded a class for the object with a different SerialVersionUID than the corresponding sender’s class, it will throw the InvalidClassException.

We can declare our own SerialVersionUID for the Serializable class. The SerialVersionUID will be declared as Static Final and Long type.

See the syntax:

private static final long serialVersionUID = 10L;

Let’s try an example that implements serialization and deserialization with the SerialVersionUID. See example:

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());
  }
}

If the Serializable class does not explicitly declare a SerialVersionUID, then the runtime will calculate the default SerialVersionUID for that class based on the aspects. Now let’s see the output for the code above.

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

Some important points about the SerialVersionUID based on the above scenario:

  1. The static and transient fields are ignored during the serialization, and after deserialization, the transient and non-static final fields will become null.
  2. For the serialization, we need to handle the IOException, and for the deserialization, we need to IOException and ClassNotFoundException. That means the deserialized class type should be in the class path.
  3. The methods ObjectInputStream.readObject() and ObjectOutputStream.writeObject(object) are used for the serialization and deserialization operation.
  4. Serialization and deserialization can be used to clone and copy the objects, which is comparatively slower than regular cloning operations.
  5. The uninitialized, non-serializable, and non-transient instances are tolerated.
  6. While modifying the class that implements the java.io.Serializable, we must be careful because if a class does not contain a SerialVersionUID, then a SerialVersionUID will be generated by the compiler.
  7. Calculating the SerialVersionUID is based not only on the fields but also on other aspects like constructors, implement clauses, etc. This means we should explicitly declare a SerialVersionUID, which will also maintain backward compatibility.
Author: 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