Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable. — from Java docs.
Quite vague. In a nutshell, sometime we want to share the state of a class instance,then we will store the class variables to e.g. a file, then restore it back to a class object, in this moment, we will use the Serializable
interface.
Let’s create a class object to understand it.
This is a Person
object implements Serializable
which has AGE
, name
, gender
and bankNumber
.
Then, we create the method to store the state of object instance and restore back to the object. From the code below, we are trying to store the state of object to D drive named person.txt
. Then, we try to read person.txt
and get back the state.
You can open the person.txt from the file explorer. There are some meaningless string in the file since the data stored in binary format and not for human read.
The out put is:
serialize
deserialize
Person{name='billy', gender='male', bankNumber='null', AGE='20'}
We can find out that the bankNumber
is null. Why?
All variable(no matter public
or private
) marked with transient
will not store the state.
We find that the static
variable AGE
is not null, does it mean that we can store static
variable? The answer is no and we will prove it.
Let’s comment out serializePerson();
and change the AGE
value to “10”
.
in class Personprivate static String AGE = "10";in public static void main//serializePerson();
Person person = deserializePerson();
System.out.println(person.toString());
Run the program again. As we already have person.txt
file, the program will restore the value base on it, so, if the file stored static
variable AGE
's value, it should be 20 instead of 10.
The output is:
deserialize
Person{name='null', gender='male', bankNumber='null', AGE='10'}
Now, we can conclude that Serializable
will ignore the static
variable and transient
variable.
Now, consider a situation, we want to add a new variable address
to Person
. After that, we try to restore the data from person.txt
.
in class Personprivate String address;in public static void main//serializePerson();
Person person = deserializePerson();
System.out.println(person.toString());
An error occurred. It said the serialVersionUID
has changed.
Exception in thread "main" java.io.InvalidClassException: test.Person; local class incompatible: stream classdesc serialVersionUID = -5617285546907292941, local class serialVersionUID = 7380129921541072321
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 java.io.ObjectInputStream.readObject(Unknown Source)
at test.main.deserializePerson(main.java:33)
at test.main.main(main.java:15)
what is serialVersionUID
?
The serialization runtime associates with each serializable class a version number, called a
serialVersionUID
, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a differentserialVersionUID
than that of the corresponding sender's class, then deserialization will result in anInvalidClassException
. A serializable class can declare its ownserialVersionUID
explicitly by declaring a field namedserialVersionUID
that must be static, final, and of typelong
.
Since we do not explicitly declare serialVersionUID
in Person
. Java will automatically generate one for us. We added address
, Java will generated another serialVersionUID
which does not match the old one in person.txt
.
Let’s add a serialVersionUID
to Person
.
in class Personprivate static final long serialVersionUID = 1L;in public static void mainserializePerson();
Person person = deserializePerson();
System.out.println(person.toString());
It will now generate a new person.txt
with our declared serialVersionUID
. You can add some new variables and try to restore the data from person.txt
. Everything should work fine, of cause, for the newly added variables, person.txt
does not have the data, so it should be default data.