What is serialVersionUID and Why do we need it

If you have done coding in tech industry then you may have gone through the serialVersionUID listed in the java class. Today, I will uncover what is serialVersionUID and why do we need it?

Read Also :   Java Collections Interview Questions 
 
But first we need to understand

What is Serialization?


Serialization is used to save the state of an object. Real world example is video-game. While playing video-games, if you press the pause button and again click on the play button , the game continue from the paused state. So pausing the game is serialization as we are saving the state of the game. Continue playing from the paused state is deserialization.

What is Serializable class



Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Serializable interface has no fields and methods.It is a marker interface.
Classes that do not implement this interface will not have any of their state serialized or deserialized.

Now, back to our main question 

What is serialVersionUID?




serialVersionUID is used to make sure the same class is loaded during deserialization (that was used for serialization process).It works like a version control in a Serializable class.

Syntax of serialVersionUID



ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;


Note: serialVersionUID must be static,final and of type long. You can assign any value of your choice to it.

What if You Do not Provide serialVersionUID in Serializable class



Serialization process must include serialVersionUID. But it is optional for the developer to provide serialVersionUID in the serializabale java source file. If you do not add serialVersionUID to the java source file, then serialization runtime will generate a serialVersionUID and associate it with the class.The serialized object will contain serialVersionUID plus the other data.

If you do not add serialVersionUID in the Serializable class, then you will get this warning message

The serializable class xxxx does not declare a static final serialVersionUID field of Type long. 



Exception to the Static rule



There is a rule in serialization that "static fields are not serialized". But serialVersionUID is an exception. Static serialVersionUID is also saved in the serialize object.

How serialVersionUID works?



If a class is serialized, then the object of the class contains serialVersionUID along with other data.
Later, when serialized object is deserialized, the serialVersionUID of the deserialized object is compared with the serialVersionUID of the loaded class.
If the serialVersionUID's do not match then InvalidClassException is thrown.

Example of serialVersionUID



The below class is serialized first and has serialVersionUID as 1L.


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable; 
 
 class Employee implements Serializable {
 
// serialVersionUID declaration
private static final long serialVersionUID = 1L;
private String empId;
 
//Constructor
public Employee(String empId){
    this.empId = empId;
 }
 
// Get EmployeeId
public String getEmployeeId(){
    return empId;
 }
} 
 
 public class TestSerialVersionUID {
  public static void main(String args[]) throws IOException, 
  ClassNotFoundException {
    Employee emp = new Employee("10");
 
    //Serialize object 
 
    System.out.println("Serialization process is completed");
    FileOutputStream fos = new FileOutputStream("c:\\employee.ser");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(emp); 
 
    // Deserialize object 
 
    FileInputStream fis = new FileInputStream("c:\\employee.ser");
    ObjectInputStream ois = new ObjectInputStream(fis);
    Employee deserializedObject = (Employee) ois.readObject();
    System.out.println("DeSerialization process is completed.");
    System.out.println("Employee's id : " + deserializedObject.getEmployeeId());
  }
}


Output is :

Serialization process is completed
DeSerialization process is completed
Employee's id :10 


The above output shows that our object is correctly serialized and deserialized.

Note : File employee.ser is created on disk and it is still there even after the program finished.

Now, let's check whether we can read that file once again. There is no creation process this time. To make sure there is no creation, comment out the lines below  Serialize object  and above Deserialize object as shown below.

public class TestSerialVersionUID {


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

    Employee emp = new Employee("10");

    //Serialize object


    //System.out.println("Serialization process is completed");

    //FileOutputStream fos = new FileOutputStream("c:\\employee.ser");

    //ObjectOutputStream oos = new ObjectOutputStream(fos);

    //oos.writeObject(emp);


    // Deserialize object
   

    FileInputStream fis = new FileInputStream("c:\\employee.ser");

    ObjectInputStream ois = new ObjectInputStream(fis);

    Employee deserializedObject = (Employee) ois.readObject();

    System.out.println("DeSerialization process is completed.");

    System.out.println("Employee's id : " + deserializedObject.getEmployeeId());

  }

}


Main method will start with reading the file from the disk and deserialize the data stored in it. As the file is exactly the same and our class didn't change either, the output should be exactly same as above.

Output :

DeSerialization process is completed
Employee's id :10




Testing



Now change the Employee class serialVersionUID to 2L i.e

private static final long serialVersionUID = 2L;

Then comment out the lines below  //Serialize object  and above //Deserialize object as shown below.


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable; 

 

 class Employee implements Serializable {
 

// serialVersionUID declaration
private static final long serialVersionUID = 2L;
private String empId;
 

//Constructor
public Employee(String empId){
    this.empId = empId;
 }
 

// Get EmployeeId
public String getEmployeeId(){
    return empId;
 }
} 

 

 public class TestSerialVersionUID {
  public static void main(String args[]) throws IOException, 
  ClassNotFoundException { 
 
  Employee emp = new Employee("10");

    //Serialize object 

 

   // System.out.println("Serialization process is completed");
   // FileOutputStream fos = new FileOutputStream("c:\\employee.ser");
   // ObjectOutputStream oos = new ObjectOutputStream(fos);
   // oos.writeObject(emp); 

 

    // Deserialize object 

 

    FileInputStream fis = new FileInputStream("c:\\employee.ser");
    ObjectInputStream ois = new ObjectInputStream(fis);
    Employee deserializedObject = (Employee) ois.readObject();
    System.out.println("DeSerialization process is completed.");
    System.out.println("Employee's id : " + deserializedObject.getEmployeeId());
  }
}


Now if you try to execute it, you will get following exception.

Exception in thread "main" java.io.InvalidClassException: Employee; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

    at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
    at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
    at java.io.ObjectInputStream.readClassDesc(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at TestSerialVersionUID.main(TestSerialVersionUID.java:21)

This is because you write a serialization class with serialVersionUID "1L" but try to deserialize it with updated serialVersionUID ="2L"

The serialVersionUID must be same during the serialization and deserialization proces. 


Strongly recommended : Declare serialVersionUID



1. It is strongly recommended that all serializabale classes  explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization.
Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value.

2. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible

References

Oracle docs

About The Author

Subham Mittal has worked in Oracle for 3 years.
Enjoyed this post? Never miss out on future posts by subscribing JavaHungry