First I need to explain what serialization is.
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.
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. However, the first superclass in the hierarchy of the serializable class, that does not implements Serializable interface, MUST have a no-arg constructor. If this is violated, readObject() will produce a java.io.InvalidClassException in runtime
All primitive types are serializable.
Transient fields (with transient modifier) are NOT serialized, (i.e., not saved or restored). A class that implements Serializable must mark transient fields of classes that do not support serialization (e.g., a file stream).
Static fields (with static modifier) are not serialized.
When Object
is serialized, Java Runtime associates the serial version number aka, the serialVersionID
.
Where we need serialVersionID:
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 InvalidClassCastException
.
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.
import java.io.Serializable;
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String empname;
private byte empage;
public String getEmpName() {
return name;
}
public void setEmpName(String empname) {
this.empname = empname;
}
public byte getEmpAge() {
return empage;
}
public void setEmpAge(byte empage) {
this.empage = empage;
}
public String whoIsThis() {
return getEmpName() + " is " + getEmpAge() + "years old";
}
}
Create Serialize Object
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Writer {
public static void main(String[] args) throws IOException {
Employee employee = new Employee();
employee.setEmpName("Jagdish");
employee.setEmpAge((byte) 30);
FileOutputStream fout = new
FileOutputStream("/users/Jagdish.vala/employee.obj");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(employee);
oos.close();
System.out.println("Process complete");
}
}
Deserialize the object
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Reader {
public static void main(String[] args) throws ClassNotFoundException, IOException {
Employee employee = new Employee();
FileInputStream fin = new FileInputStream("/users/Jagdish.vala/employee.obj");
ObjectInputStream ois = new ObjectInputStream(fin);
employee = (Employee) ois.readObject();
ois.close();
System.out.println(employee.whoIsThis());
}
}
NOTE: Now change the serialVersionUID of the Employee class and save:
private static final long serialVersionUID = 4L;
And execute the Reader class. Not to execute the Writer class and you will get the exception.
Exception in thread "main" java.io.InvalidClassException:
com.jagdish.vala.java.serialVersion.Employee; local class incompatible:
stream classdesc serialVersionUID = 1, local class serialVersionUID = 4
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)