Java interview – Serialization

Java Serialization Interview Questions and Answers

1. What is Serialization?

Serialization is the process of converting an object and its states to a binary stream that can then be saved into a database, cached or sent over the network to another JVM.

2. What is Deserialization?

Deserialization is the process of converting back a serialized object.

import java.io.Serializable;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public class User implements Serializable {

	private static final long serialVersionUID = 3L;

	private String name;

	private int age;

	private String email;

	transient private double height;

	//setters and getters

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializationDemo {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		String path = "serialized_user.ser";

		User serializedUser = serialize(path);

		System.out.println("serializedUser=" + serializedUser.toString());

		User deserializedUser = deserialize(path);
		
		System.out.println("deserializedUser=" + deserializedUser.toString());

	}

	private static User serialize(String path) throws IOException {

		FileOutputStream fileStream = new FileOutputStream(path);

		ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);

		User user = new User();
		user.setAge(21);
		user.setName("Laulau");
		user.setEmail("folaukaveinga@gmail.com");
		user.setHeight(6.3);

		objectStream.writeObject(user);

		objectStream.close();
		fileStream.close();

		return user;
	}

	private static User deserialize(String path) throws IOException, ClassNotFoundException {
		FileInputStream fileInputStream = new FileInputStream(path);
		ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

		User user = (User) objectInputStream.readObject();

		objectInputStream.close();
		fileInputStream.close();

		return user;
	}

}

Result

serializedUser=User[name=Laulau,age=21,email=folaukaveinga@gmail.com]
deserializedUser=User[name=Laulau,age=21,email=folaukaveinga@gmail.com]

3. What is Externalization?

Serialization is not very efficient. If you serialize bloated objects having a lot of attributes and properties, you do not wish to serialize. This is where Externalization in Java comes into the picture. Externalization is an advanced way of serialization. It is whenever you need to customize the serialization mechanism.

The class you want to be externalized must implement the Externalizable interface, then serialization of the object will be done using the method writeExternal(). When the Externalizable object is reconstructed at the receiver’s end, an instance will be created using no-argument constructor and this method is called readExternal().

This basically serves the purpose of custom Serialization, where you can decide what to store in a stream.

When to use Externalization?

When you want or need to serialize only part of an object, Externalization is the best option.

How to use Externalization?

By implementing the Externalizable interface, you control the process of reading and writing the objects during serialization and de-serialization process, you need to have the object’s class implemented the interface java.io.Externalizable. Only then you can implement your own code to read and write the object’s states. The methods, readExternal() and writeExternal() are defined by the Externalizable interface.

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public class Member implements Externalizable {

	public static final long serialVersionUID = 2L;

	private String name;

	private int age;

	private String email;

	transient private double height;

	// setters and getters

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		System.out.println("writing object state...");
		// TODO Auto-generated method stub
		out.writeObject(name);
		out.writeObject(email);
		out.writeInt(age);
		out.writeDouble(height);
	}

	@Override
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		System.out.println("reading object state...");
		this.name = (String) in.readObject();
		this.email = (String) in.readObject();
		this.age = in.readInt();
		this.height = in.readDouble();
	}
}
public class ExternalizeDemo {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		String path = "externalized_member.ser";

		Member externalizedMember = serialize(path);

		System.out.println("externalizedMember=" + externalizedMember.toString());

		Member dexternalizedMember = deserialize(path);

		System.out.println("dexternalizedMember=" + dexternalizedMember.toString());
	}

	private static Member serialize(String path) throws IOException {

		FileOutputStream fileStream = new FileOutputStream(path);

		ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);

		Member member = new Member();
		member.setAge(21);
		member.setName("Laulau");
		member.setEmail("folaukaveinga@gmail.com");
		member.setHeight(6.3);

		System.out.println(member.toString());

		objectStream.writeObject(member);

		objectStream.close();
		fileStream.close();

		return member;

	}

	private static Member deserialize(String path) throws IOException, ClassNotFoundException {
		FileInputStream fileInputStream = new FileInputStream(path);
		ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

		Member member = (Member) objectInputStream.readObject();

		objectInputStream.close();
		fileInputStream.close();

		return member;
	}
}

Result

Member[name=Laulau,age=21,email=folaukaveinga@gmail.com]
writing object state...
externalizedMember=Member[name=Laulau,age=21,email=folaukaveinga@gmail.com]
reading object state...
dexternalizedMember=Member[name=Laulau,age=21,email=folaukaveinga@gmail.com]

4. What are the differences between Serialization and Externalization?

Externalizable provides us with writeExternal() and readExternal() methods that give us control on what attributes and values to serialize. Correct implementation of the Externalizable interface can improve the performance of application drastically.

ExternalizationSerialization
UIDNo need to have it but for best practice you must have itNeeds a serialVersionUID
StorageStore the data per attribute.Store the whole object directly.
AccessProvides complete control to the serialization and deserialization process.No access

5. How many methods does Serializable have?

Zero. Serializable is a marker interface.

6. What is a serialVersionUID? What happens when you don’t explicitly provide?

serialVersionUID is a version control id. It is basically the hashcode of the object. So if you change the object(add or remove an attribute) then the hashcode will be different so an already serialized object will not be able to deserialize. Java serialization process relies on correct serialVersionUID for recovering the state of the serialized object and throws java.io.InvalidClassException in case of serialVersionUID mismatch

When an object is serialized, the serialVersionUID is serialized along with the other contents. Later when that is deserialized, the serialVersionUID from the deserialized object is extracted and compared with the serialVersionUID of the loaded class. If the numbers do not match then, InvalidClassException is thrown.

serialVersionUID is a 64-bit hash of the class name, interface class names, methods and fields. Serialization runtime generates a serialVersionUID if you do not add one. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations and can produce different serialVersionUID in different environments.


If you don’t provide it, Java will provide it for you.

7. What happens if an object is serializable but it includes a reference to a non-serializable object?

Java will throw a NotSerializableException. To fix this issue you can do either one of these two things:

a. Make the non-serializable object serializable by making its class implement the Serializable interface.

b. Make the non-serializable object transient or static.

8. If a class is serializable but its superclass in not, what will be the state of the instance variables inherited from super class after deserialization?

The state will be its default value. For example:

int age; -> age = 0;

String name; -> name = null;

9. To serialize an array or a collection all the members of it must be serializable. True /False?

true

All standard implementations of collections List, Set and Map interface already implement java.io.Serializable. This means you do not really need to write anything specific to serialize collection objects. However, you should keep the following things in mind before you serialize a collection object – Make sure all the objects added in a collection are Serializable.

10. While serializing you want some of the members not to serialize, how do you achieve it?

If you don’t want any field to be part of the object’s state then declare it either static or transient based on your need and it will not be included during the serialization process.

Variables marked with transient are not included in the process of serialization and are not part of the object’s serialized state.

The static variables belong to a class are not part of the state of the object so they are not saved as part of the serialized object.

Why static variables are not serialized in Java?

The Java variables declared as static are not considered part of the state of an object since they are shared by all instances of that class. Saving static variables with each serialized object would have following problems

  • It will make redundant copy of same variable in multiple objects which makes it in-efficient.
  • The static variable can be modified by any object and a serialized copy would be stale or not in sync with current value.

11. What should you take care of when serializing an object?

You should make sure that all the included objects are also serializable. If any of the objects is not serializable then it throws a NotSerializableException.

12. Suppose a superclass of a new class implements Serializable interface, how can you avoid new class to being serialized?

Use Externalization and exclude the new class from the serialization process.

13. What are the ways to speed up Object Serialization? How to improve Serialization performance?

The default Java Serialization mechanism is really useful, however it can have a really bad performance based on your application and business requirements. The serialization process performance heavily depends on the number and size of attributes you are going to serialize for an object. Below are some tips you can use for speeding up the marshaling and un-marshaling of objects during Java serialization process.

  • Mark the unwanted or non Serializable attributes as transient. This is a straight forward benefit since your attributes for serialization are clearly marked and can be easily achieved using Serialzable interface itself.
  • Save only the state of the object, not the derived attributes. Some times we keep the derived attributes as part of the object however serializing them can be costly. Therefore consider calcualting them during de-serialization process.
  • Serialize attributes only with NON-default values. For examples, serializing a int variable with value zero is just going to take extra space however, choosing not to serialize it would save you a lot of performance. This approach can avoid some types of attributes taking unwanted space. This will require use of Externalizable interface since attribute serialization is determined at runtime based on the value of each attribute.
  • Use Externalizable interface and implement the readExternal and writeExternal methods to dynamically identify the attributes to be serialized. Some times there can be a custom logic used for serialization of various attributes.

14. Do constructors get invoked or run at deserialization?

When an instance of a serializable class is deserialized, the constructor does not run. If constructors were invoked it will give back the initial values rather than the value they had at the time of serialization.

15. What are the compatible and incompatible changes when dealing with versioned serialized objects during serialization?

Changes to a serializable class can be compatible or incompatible. Following is the list of changes which are compatible:

  • Adding fields – When the class being reconstituted has a field that does not occur in the stream, that field in the object will be initialized to the default value for its type.
  • Adding or removing classes – Comparing the class hierarchy in the stream with that of the current class can detect that a class has been deleted or added.
  • Adding or removing writeObject/readObject methods
  • Changing the access to a field – The access modifiers public, package, protected, and private have no effect on the ability of serialization to assign values to the fields.
  • Changing a field from static to nonstatic or transient to nontransient – When relying on default serialization to compute the serializable fields, this change is equivalent to adding a field to the class. The new field will be written to the stream but earlier classes will ignore the value since serialization will not assign values to static or transient fields.

List of incompatible changes:

  • Deleting fields
  • Changing a nonstatic field to static or a nontransient field to transient
  • Changing the declared type of a primitive field
  • Changing a class from Serializable to Externalizable or vice versa is an incompatible change since the stream will contain data that is incompatible with the implementation of the available class.
  • Changing a class from a non-enum type to an enum type or vice versa
  • Removing either Serializable or Externalizable is an incompatible change since when written it will no longer supply the fields needed by older versions of the class.
  • Changing the writeObject or readObject method
  • Moving classes up or down the hierarchy – This cannot be allowed since the data in the stream appears in the wrong sequence.

16. What are the guidelines for using serialVersionUID?

  • You must declare serialVersionUID because it gives us more control. For example, Default rules for generating serialVersionUID can be too strict in some cases. For example when the visibility of a field changes, the serialVersionUID changes too. or sometimes you just want to forbid deserialization of old serialized objects then you can just change serialVersionUID.
  • Include this field even in the first version of the class, as a reminder of its importance
  • You must not only declare it but also maintain it. You should change serialVersionUID when there is some change in the definition of data stored in the class. For example, data type of field is changed.

17. Does setting the serialVersionUID class field improve Java serialization performance?

Declaring an explicit serialVersionUID field in your classes saves some CPU time only the first time the JVM process serializes a given Class. However the gain is not significant, In case when you have not declared the serialVersionUID its value is computed by JVM once and subsequently kept in a soft cache for future use.

18. Suppose you have a class in which you serialized and stored in persistence and later modified that class to add a new field. What will happen if you deserialize the object already serialized?

It depends on whether a class has its own serialVersionUID or not. As we know that if we don’t provide serialVersionUID in our code java compiler will generate it and normally it’s equal to hashCode of the object. By adding any new field there is a chance that new serialVersionUID generated for that class version is not the same as the serialized object. In this case, Java Serialization API will throw java.io.InvalidClassException and this is the reason its recommended to have your own serialVersionUID in code and make sure to keep it same always for a single class.




Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *