- What is Serialization?
- How do you serialize an object using Serializable interface?
- How do you de-serialize in Java?
- What do you do if only parts of the object have to be serialized?
- How do you serialize a hierarchy of objects?
- Are the constructors in an object invoked when it is de-serialized?
- Are the values of static variables stored when an object is serialized?
Serialization helps us to save and retrieve the state of an object.
- Serialization => Converts object state to some internal object representation.
- De-Serialization => The reverse. Convert internal representation to object.
Two important methods:
ObjectOutputStream.writeObject()
// serialize and write to file ObjectInputStream.readObject()
// read from file and deserialize
To serialize an object, it should implement Serializable
interface. In the example below, Rectangle
class implements Serializable
interface. Note that Serializable
interface does not declare any methods to be implemented.
The below example shows how an instance of an object can be serialized. We are creating a new Rectangle
object and serializing it to a file Rectangle.ser.
class Rectangle implements Serializable {
public Rectangle(int length, int breadth) {
this.length = length;
this.breadth = breadth;
area = length * breadth;
}
int length;
int breadth;
int area;
}
FileOutputStream fileStream = new FileOutputStream("Rectangle.ser");
ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
objectStream.writeObject(new Rectangle(5, 6));
objectStream.close();
Below example shows how an object can be deserialized from a serialized file. A rectangle
object is deserialized from the file Rectangle.ser.
FileInputStream fileInputStream = new FileInputStream("Rectangle.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(
fileInputStream);
Rectangle rectangle = (Rectangle) objectInputStream.readObject();
objectInputStream.close();
System.out.println(rectangle.length);
System.out.println(rectangle.breadth);
System.out.println(rectangle.area);
We mark all the properties of the object which should not be serialized as transient. Transient attributes in an object are not serialized. Area in the previous example is a calculated value. It is unnecessary to serialize and deserialize. We can calculate it when needed. In this situation, we can make the variable transient. Transient variables are not serialized. (transient int area;
)
class Rectangle implements Serializable {
public Rectangle(int length, int breadth) {
this.length = length;
this.breadth = breadth;
area = length * breadth;
}
int length;
int breadth;
transient int area;
}
If you run the program again, you would get the following output:
System.out.println(rectangle.length);
System.out.println(rectangle.breadth);
System.out.println(rectangle.area);
Note that the value of rectangle.area
is set to 0
. Variable area is marked transient. So, it is not stored into the serialized file. And when de-serialization happens, area value is set to default value, i.e., 0
.
Objects of one class might contain objects of other classes. When serializing and de-serializing, we might need to serialize and de-serialize entire object chain. All classes that need to be serialized have to implement the Serializable
interface. Otherwise, an exception is thrown. Look at the class below. An object of class House
contains an object of class Wall
.
House
implements Serializable
. However, Wall
doesn't implement Serializable
. When we try to serialize an instance of House
class, we get the following exception:
class House implements Serializable {
public House(int number) {
super();
this.number = number;
}
Wall wall;
int number;
}
class Wall{
int length;
int breadth;
int color;
}
Output
Exception in thread "main" java.io.NotSerializableException: com.rithus.serialization.Wall
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
This is because Wall
is not serializable. Two solutions are possible.
- Make
Wall
transient. Wall
object will not be serialized. This causes the wall
object state to be lost. - Make
Wall
implement Serializable
. Wall
object will also be serialized and the state of wall
object along with the house will be stored.
Option 1
class House implements Serializable {
public House(int number) {
super();
this.number = number;
}
transient Wall wall;
int number;
}
Option 2
class Wall implements Serializable {
int length;
int breadth;
int color;
}
With both these programs, earlier main
method would run without throwing an exception. If you try de-serializing, in example 2, state of wall
object is retained whereas in example 1, state of wall
object is lost.
No. When a class is De-serialized, initialization (constructors, initializers) does not take place. The state of the object is retained as it is.
Static Variables are not part of the object. They are not serialized.