:::section{.main}
Serialization in java is the process of converting the state of an object into a byte stream. A byte stream is a Java I/O (Input/Output) stream, essentially a flow of data that a programmer can read from or write to. Byte Streams read or write one byte of data at a time.
However, we must convert these byte streams back to their respective Objects to use them again. This reverse process of converting an object into byte-stream is called Deserialization.
Serialization in Java can be implemented using the java.io.Serializable
interface. The writeObject()
method of the ObjectOutputStream
class is used for serializing an Object. To make a Java object serializable, we implement the java.io.Serializable
interface.
While Serialization, the writeObject()
method is used. Meanwhile, in Deserialization, the readObject()
method is used. Also, for an object to be made serializable, it is mandatory for the object’s class to implement the Serializable interface.
The Serializable
interface tells the JVM (Java Virtual Machine) that the objects of this class are ready for serialization and/or deserialization. The code that we write is called source code. We know that machines do not understand the human language. To bridge the gap, we need to translate the source code. This is where the JVM comes in. It converts source code to something called bytecode, which is then translated to the machine language.
:::
:::section{.main}
Let’s look at one example to show how serialization in Java works programmatically. Here, we are creating a Student
class and serializing the object of the Student
class.
Explanation:
Object
of type Student
. A text file called storeObject
is created with the help of the FileOutputStream
class.FileOutputStream
is an output stream that is used to write data into a file. Next, the ObjectOutputStream
class is used to write the object as an OutputStream
.writeObject(Object ob)
is used to serialize objects into byte-streams.Next, let’s look at the code for deserializing the same object. We will use the readObject()
method of the ObjectInputStream
class to deserialise the object.
Output:
Explanation:
storeObject.txt
file is accessed with the help of the FileInputStream
, which is used to read data from a file.ObjectInputStream
, which converts the objects from the byte stream that was written using ObjectOutputStream
.readObject()
method is used to deserialize objects.Hence, the process from object to byte stream is complete.
:::
:::section{.main}
When a parent class implements the Serializable interface, the child classes do not have to do so. This is a case of Serialization with Inheritance. Inheritance is when a child class extends a parent class and inherits its properties. Hence, the names - parent and child.
Example:
Since Student
extends Child
, which extends the Serializable interface, there is no need for the Student
class itself to extend this interface.
:::
:::section{.main}
If a class Student has an object of type Child and if class Student were to implement the Serializable interface and not B, Java would throw a NotSerializableException
. Let’s see in the code:
Example:
The above code snippet would throw a NotSerializableException
when a class Student
object is serialized. Class Student
is said to have a relationship with class Child. This is called Aggregation (HAS-A Relationship).
:::
:::section{.main}
Static data members are volatile and can change during the serialization to deserialization process. Static means the data member is the only copy of the class, and any change made to it will be felt throughout the program. In other words, it belongs to the whole class.
Consider the below code where x is a static variable:
Example:
Output:
Explanation:
:::
:::section{.main}
When dealing with arrays or collections, all contained objects must be serializable. If any object within them lacks serializability, the serialization process will encounter failure.
:::
:::section{.main}
The serialVersionUID
is a constant. So, while the whole object to byte-stream to object takes place, we need to be sure that the conversion from byte-stream to object is correct.
serialVersionUID
attribute to remember versions of a Serializable
class and verify that a class and the serialized object are compatible.serialVersionUID
is optional. If the programmer does not define this constant, Java does it for us.The serialization at runtime associates with each serializable class a serialVersionUID
, which is used during deserialization to verify that the object that was converted to byte-stream is the one that is being retrieved.
What if we do not want to save, i.e. serialize, the state of some data member of the class that gets serialized?
In that case, we use a reserved keyword with the data member(s) that we do not want to serialize, like below:
Take a look at the example below:
Output:
Explanation:
The last print statement will return null as stu_Addr
is a transient variable, and as such, it will not get serialized and will lose its value.
:::
:::section{.main}
Regarding serialization, final variables are serialized directly by their values. Therefore, marking a final variable as transient serves no purpose, as the compiler assigns the value to the final variable.
In Java, marking a data member as transient means it won't be serialized when the object is written to a file or transferred over a network.
:::
:::section{.summary}
:::