Java Serialization Interview Questions
Serialization, De-Serialization Example
package learncode;
import java.io.Serializable;
public class ClassA implements Serializable {
private static final long serialVersionUID = 1L;
private int a;
public ClassA() {
this.a = 10;
System.out.println("Constructor called. a=" + a);
}
public void print() {
System.out.println("print method called. a=" + a);
}
}
MainTest.java Class
package learncode;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class MainTest {
public static void main(String[] arg) {
ClassA classA = new ClassA();
classA.print();
System.out.println("Exit Main");
}
}
Output:
Constructor called. a=10
print method called. a=10
Exit Main
Modify test class to write "classA" object in a file
package learncode;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class MainTest {
public static void main(String[] arg) {
ClassA classA = new ClassA();
classA.print();
System.out.println("Exit Main");
ObjectOutputStream oos;
try {
oos = new ObjectOutputStream(new FileOutputStream("example.ser"));
oos.writeObject(classA);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Now add new test <MainTest2.java> class to read previously created file
package learncode;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class MainTest2 {
public static void main(String[] arg) {
ObjectInputStream ios = null;
try {
ios = new ObjectInputStream(new FileInputStream("example.ser"));
Object object = ios.readObject();
if (object instanceof ClassA) {
ClassA classA = (ClassA) object;
classA.print();
}
} catch (IOException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
ios.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Output:
print method called. a=10
What is Object Serialization and Deserialization?
Answer: Serialization is a mechanism of converting the state of an object into a byte stream. Deserialization is the reverse process where the byte stream is used to recreate the actual Java object in memory. This mechanism is used to persist the object.
You are making a class Serializable by implementing Serializable interface. Which methods are to be implemented?
Answer: None
What methods are there in Serializable interface?
Answer: Serializable interface is a marker interface and has no methods. It simply tells the object serialization tools that the class is Serializable. Refer Class A implementation.
In which scenarios serialization should be used?
Answer: Objects are serialized when sending over the network.
How can the Java objects exist beyond the lifetime of the virtual machine?
Answer: Object serialization allows Java objects to live beyond the lifetime of JVM.
What can be the cause of NotSerializableException during object serialization?
Answer: If a class is to be serialized, it has to implement Serializable interface. It is also important that all the objects included in that class are also Serializable. NotSerializableException is thrown if any of the included objects is not Serializable.
Are all primitive wrapper classes Serializable?
Answer: Yes.
I have a class called Student that is Serializable. It has an instance variable of type String called 'name'. Since 'name' is not of primitive type, should we expect serialization failure?
..
public class Student implements Serializable {
private String name;
..
Answer: java.lang.String itself is Serializable, therefore Student class can be serialized.
What will happen if I try to serialize an object of a class that implements Serializable interface, but also includes a nonSerializable object?
Answer: java.io.NotSerializableException will be thrown at runtime.
Is it correct to say that when an object is de-serialized, its constructor is called?
Answer: De-serialization means restoring the serialized object and not reconstructing it. The constructor is not called in the de-serialization process. Refer above example output.
What is a serialVersionUID? How is it used?
Answer: A Serial Version UID is a unique identifier for a serializable class to make sure that the serialised and the deserialised object refers to the same version, The Java compiler creates a unique serialVersionUID if it is not defined in the program. It is best to define a serialVersionUID for every serializable class as otherwise the JVM will not able to identify the class when its version changes. Every time you change an attribute of the serializable class, the JVM creates a new serialVersionUID if it is not user-defined. So the best practice is to define a serialVersionUID for all serializable classes in Java so that the multiple versions will refer to the same object.
What is the purpose of using serialVersionUID?
Answer: serialVersionUID provides versioning system for every Serializable class. During de-serialization process, serialVersionUID provides means of checking whether data read from the input stream is compatible with the current class definition.
private static final long serialVersionUID = 1L;
serialVersionUID is a static field declared in a Serializable class. Is it also serialized?
Answer: serialVersionUID is a 'static field that is also serialized along with the other data. During de-serialization, the de-serialized serialVersionUID has to match to the serialVersionUID declared in the class definition.
What happens if serialVersionUID of de-serialized object does not match to the one declared in the class definition?
Answer: java.io.InvalidClassException is thrown.
Consider that you have a Serializable class without serialVersionUID. How compiler will handle this?
Answer: Java compiler adds serialVersionUID automatically and its value is based on the fields declared in the class.
Consider the following scenario:
You have a Serializable class without serialVersionUID defined. You serialize it. You add a new instance variable in your Serializable class and de-serialize its already serialized instance.
What will happen?
Answer: Since serialVersionUID was not defined in the Serializable class, JVM will generate that. Once you add or remove instance variables in the Serializable class, the value of serialVersionUID will change. In the given scenario, java.io.InvalidClassException will be thrown.
Now modify Class A like below
package learncode;
import java.io.Serializable;
public class ClassA implements Serializable {
private static final long serialVersionUID = 1L;
private int a;
private transient int b = 30;
private static String s;
public ClassA() {
this.a = 10;
System.out.println("Constructor called. a=" + a);
System.out.println("Constructor called. b=" + b);
b = 100;
s = "Java";
}
public void print() {
System.out.println("print method called. a=" + a);
System.out.println("print method called. b=" + b);
System.out.println("print method called. s=" + s);
}
}
Now run MainTest.java and check the output
Constructor called. a=10
Constructor called. b=30
print method called. a=10
print method called. b=100
print method called. s=Java
Exit Main
Now run MainTest2.java to deserialize the saved object. Output:
print method called. a=10
print method called. b=0
print method called. s=null
How to exclude certain variables from object's serialized state?
Answer: To exclude variables from the process of serialization, they should be marked as transient.
private transient int b = 30;
Is it true to say that during object serialization class and instance variables that are not marked as transient are also serialized?
Answer: No. Static variables belonging to the class are not saved as the part of serialized object. Also the transient class variables will not be part of serialized object.
Once de-serialization is done, what values will transient variables get?
Answer: Transient variables get default values after de-serialization.
ClassB.java. Create this new class
package learncode;
import java.io.Serializable;
public class ClassB implements Serializable {
private static final long serialVersionUID = 1L;
public ClassB() {
System.out.println("ClassB constructor called");
}
}
Modify ClassA.java as below
package learncode;
public class ClassA extends ClassB {
private static final long serialVersionUID = 1L;
private int a;
private transient int b = 30;
private static String s;
public ClassA() {
this.a = 10;
System.out.println("Constructor called. a=" + a);
System.out.println("Constructor called. b=" + b);
b = 100;
s = "Java";
}
public void print() {
System.out.println("print method called. a=" + a);
System.out.println("print method called. b=" + b);
System.out.println("print method called. s=" + s);
}
}
Now run MainTest.java. Output:
ClassB constructor called
Constructor called. a=10
Constructor called. b=30
print method called. a=10
print method called. b=100
print method called. s=Java
Exit Main
Now run MainTest2.java. Output:
print method called. a=10
print method called. b=0
print method called. s=null
Consider the following scenario:
public class Parent implements Serializable
...
public class Child extends Parent
...
Is Child class Serializable?
Answer: Child class inherits serialization from its object hierarchy and it is Serializable. [Refer above example]
Consider the following scenario:
public class ClassA extends ClassB implements Serializable{
ClassA extends from ClassB.
ClassA implements Serializable.
ClassA instance is serialized.
ClassA instance is de-serialized.
What values will the variables of ClassB get?
Answer: ClassB's constructor will run and the variables will get the values assigned during the construction of the object.
Now modify ClassB.java. Remove Serializable implementation.
package learncode;
public class ClassB {
public ClassB() {
System.out.println("ClassB constructor called");
}
}
Now modify ClassA.java. Implement Serializable.
package learncode;
import java.io.Serializable;
public class ClassA extends ClassB implements Serializable {
private static final long serialVersionUID = 1L;
private int a;
private transient int b = 30;
private static String s;
public ClassA() {
this.a = 10;
System.out.println("Constructor called. a=" + a);
System.out.println("Constructor called. b=" + b);
b = 100;
s = "Java";
}
public void print() {
System.out.println("print method called. a=" + a);
System.out.println("print method called. b=" + b);
System.out.println("print method called. s=" + s);
}
}
Now run MainTest.java. Output:
ClassB constructor called
Constructor called. a=10
Constructor called. b=30
print method called. a=10
print method called. b=100
print method called. s=Java
Exit Main
Now run MainTest2.java. Output:
ClassB constructor called
print method called. a=10
print method called. b=0
print method called. s=null
Assume you have a Serializable class where its super class does not implement Serializable interface. The super class defines a no-argument constructor and a String argument constructor: Which constructor of the super class will get called during de-serialization?
Answer: No-argument constructor will get called. It should be accessible to the Serializable subclass class. [Refer above example]
Now modify ClassA.java as below:
package learncode;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class ClassA implements Serializable {
private static final long serialVersionUID = 1L;
private int a;
private transient int b = 30;
private static String s;
private List<String> list;
public ClassA() {
this.a = 10;
list = new ArrayList<String>();
list.add("Raj");
System.out.println("Constructor called. a=" + a);
System.out.println("Constructor called. b=" + b);
b = 100;
s = "Java";
}
public void print() {
System.out.println("print method called. a=" + a);
System.out.println("print method called. b=" + b);
System.out.println("print method called. s=" + s);
System.err.println("print method called. list=" + list.toString());
}
}
Now run MainTest.java. Output:
Constructor called. a=10
Constructor called. b=30
print method called. a=10
print method called. b=100
print method called. s=Java
print method called. list=[Raj]
Exit Main
Now run MainTest2.java. Output:
print method called. a=10
print method called. b=0
print method called. s=null
print method called. list=[Raj]
I wish to serialize a collection. Is it a must to have all its members Serializable?
Answer: Yes. All members of a collection or an array must be Serializable in order to Serialize it.
Difference between Serialization and Externalization in Java
Serializable | Externalizable |
---|---|
A serializable interface is used to implement serialization. | An externalizable interface used to implement Externalization |
Serializable is a marker interface i.e. it does not contain any method. | The externalizable interface is not a marker interface and thus it defines two methods writeExternal() and readExternal(). |
Serializable interface passes the responsibility of serialization to JVM and the programmer has no control over serialization, and it is a default algorithm. | The externalizable interface provides all serialization responsibilities to a programmer and hence JVM has no control over serialization. |
Serialization using a serializable interface has bad performance. | Serialization using an externalizable interface has better performance. |
Default serialization does not require any no-arg constructor. | A public no-arg constructor is required while using an Externalizable interface. |
It is hard to analyze and modify class structure because any change in structure may break serialization. | It is relatively easy to analyze and modify class structure because of complete control over serialization logic. |
Using a serializable interface we save the total object to a file, and it is not possible to save part of the object. | Base on our requirements we can save either the total object or part of the object. |
Transient keywords play an important role here. | Transient keywords won’t play any role. |
Example
class ExternalizableExample implements Externalizable {
Integer id;
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt( id );
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.id = in.readInt();
}
}
//....................................................
class SerializableExample implements Serializable {
private static final long serialVersionUID = 5081877L;
String name;
}
Externalizable Demo
package learncode;
// Java Program to illustrate Externalizable
// Importing input output classes
import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
// Main Class
// Class implementing externalizable class
public class ExternalizableDemo implements Externalizable {
// Member variables of this class
String name;
int age;
int jobId;
// Constructors of this class
// Constructor 1
// No-argument constructor
public ExternalizableDemo() {
// Display message
System.out.println("Public no-argument constructor");
}
// Constructor 2
// Default constructor
public ExternalizableDemo(String name, int age, int jobId) {
// This keyword refers to current object itself
this.name = name;
this.age = age;
this.jobId = jobId;
}
// Implementing write external method
public void writeExternal(ObjectOutput out) throws IOException {
// Writing name and age to file
out.writeObject(name);
out.writeInt(age);
}
// Implementing readExternal method
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// Reading name from file
name = (String) in.readObject();
// Reading age from file
age = in.readInt();
}
// Main method
public static void main(String[] args) throws Exception {
// Creating an object of type ExternalizableDemo
ExternalizableDemo t1 = new ExternalizableDemo("Ram", 35, 23675);
// Serialization of object
FileOutputStream fos = new FileOutputStream("abc.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(t1);
// Deserialization
FileInputStream fis = new FileInputStream("abc.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
ExternalizableDemo t2 = (ExternalizableDemo) ois.readObject();
// Display message
System.out.println("Name :" + " " + t2.name + " " + "Age :" + " " + t2.age);
}
}
Output:
Public no-argument constructor
Name : Ram Age : 35
Which methods can be overridden to change default serialization behavior in order to control complex object serialization process?
Answer: writeObject() and readObject() can be implemented to control complex object serialization process. By doing so, we can provide additional information to serialize and de-serialize objects.
Which interface is to be implemented if we want to have complete control over your class's serialization process?
Answer: java.io.Externalizable interface is to be implemented.
Name the methods that are to be overridden when Externalizable is implemented.
Answer: readExternal() and writeExternal() are to be overridden when Externalizable is implemented.