What is a serialVersionUID and why should I use it?

Serialization

Serialization allows to convert an object to a stream, for sending that object over the network OR Save to file OR save into DB for letter usage.

serialVersionUID

It is a unique identifier for each class, JVM uses it to compare the version of the class ensuring that the same class was used during Serialization is loaded during Deserialization.

There are some rules for serialization.

  • An object is serializable only if its class or its superclass implements the Serializable interface
  • An object is serializable (itself implements the Serializable interface) even if its superclass is not.
  • All primitive types are serializable.
  • Static fields (with static modifier) are not serialized.

Why we used serialVersionUID

During the deserialization to verify that sender and receiver are compatible with respect to serialization. If the receiver loaded the class with a different serialVersionID then deserialization will end with InvalidClassException.
A serializable class can declare its own serialVersionUID explicitly by declaring a field named serialVersionUID that must be static, final, and of type long.

Let’s try this with an example.

package com.sync;

import java.io.Serializable;

public class Car implements Serializable {

    private static final long serialVersionUID = 1L;
    private String carName;
    private String color;

    public Car() {
    }

    public Car(String carName, String color) {
        this.carName = carName;
        this.color = color;
    }

    public String getCarName() {
        return carName;
    }

    public void setCarName(String carName) {
        this.carName = carName;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Car{" +
                "carName='" + carName + '\'' +
                ", color='" + color + '\'' +
                '}';
    }
}

Create Serialize Object

package com.sync;

import java.io.*;

public class WriteMain {

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

        Car car1 = new Car();
        car1.setCarName("Pajero");
        car1.setColor("Green");

        FileOutputStream fos = new FileOutputStream("C://Users//BU CSE//Desktop/car.txt");

        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(car1);
        oos.close();
        System.out.println("Process Completed!");



    }
}

Deserialize the object

package com.sync;

import java.io.*;

public class ReadMain {

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


        FileInputStream fis = new FileInputStream("C://Users//BU CSE//Desktop/car.txt");

        ObjectInputStream ois = new ObjectInputStream(fis);

        Car car1 =  new Car();
        car1 = (Car) ois.readObject();
        ois.close();

        
        System.out.println(car1.getCarName() + " "+car1.getColor());

        System.out.println("Process Completed!");

    }
}

NOTE: Now change the serialVersionUID of the Employee class and save:

private static final long serialVersionUID = 3L;

And execute the ReadMain class. Not to execute the WriteMain class and you will get the exception.

"C:\Program Files\Java\jdk-15.0.2\bin\java.exe" -Didea.launcher.port=63994 "-Didea.launcher.bin.path=C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.1\bin" -Dfile.encoding=UTF-8 -classpath "D:\JAVA\Java SerialVersionUID Example\out\production\Java SerialVersionUID Example;C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.1\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMainV2 com.sync.ReadMain
 Exception in thread "main" java.io.InvalidClassException: com.sync.Car; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 3
     at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:724)
     at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2045)
     at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1895)
     at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2202)
     at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1712)
     at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:519)
     at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:477)
     at com.sync.ReadMain.main(ReadMain.java:15)
     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
     at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.base/java.lang.reflect.Method.invoke(Method.java:564)
     at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
 Process finished with exit code 1

Hope! you got understand the concept.