Pages

April 06, 2016

#Java: Part 12 Java Serialization Interview Questions and Answers for Experienced Developers(Serializable and Externalizable)

> > Part 11-Core Java Interview Questions and Answers: Comparator vs Comparable


What are Serialization and De-serialization in Java?

Serialization is a process by which you can save or transfer the state of an object by converting it to a byte stream.

During Serialization, the Object is converted into a binary format, which can be persisted into a disk or sent over the network to any other running Java virtual machine. During deserialization, the reverse process is performed by creating an object from a binary stream.

FYI, the serialization process is platform-independent, which means an object serialized on one platform can be deserialized on a different platform.

How to make a Java class Serializable?

This can be done in java by implementing java.io.Serializable interface, which is a marker interface. This interface needs to be implemented for transferring an object over a network or persistence of its state to a file. Since its a marker interface, it does not contain any methods. 

Implementation of this interface enables the conversion of objects into a byte stream and thus can be transferred. The object conversion is done by the JVM using its default serialization mechanism.

The decision to make a Class Serializable should be taken concisely because though near term cost of making a Class Serializable is low, the long-term cost is substantial and it can potentially limit your ability to further modify and change its implementation. 

Like any public API, the serialized form of an object becomes part of public API and when you change the structure of your class by implementing an additional interface, adding or removing any field can potentially break default serialization, this can be minimized by using a custom binary format but still requires a lot of effort to ensure backward compatibility.

The ObjectOutputStream contains the method writeObject() which is used for serializing an object and the ObjectInputStream contains the method readObject() used for deserializing the byte stream.


What is the use of serialVersionUID?

When working with serialized data on different JVMs we need to ensure and verify that both the sender and receiver of the serialized objects have loaded the classes for that object that are compatible with respect to the serialization. serialVersionUID is used for this verification process.

During object serialization, the default Java serialization mechanism writes the metadata about the object, which includes the class name, field names, types, and superclass. This class definition is stored as a part of the serialized object. This stored metadata enables the deserialization process to reconstitute the objects and map the stream data into the class attributes with the appropriate type.

Every time an object is serialized the java serialization mechanism automatically computes a hash value. ObjectStreamClass's computeSerialVersionUID() method passes the class name, sorted member names, modifiers, and interfaces to the secure hash algorithm (SHA), which returns a hash value called serialVersionUID or suid.

When the serialized object is retrieved, the JVM first evaluates the 'suid' of the serialized class and compares the 'suid' value with one of the objects. If the suid values match then the object is said to be compatible with the class and hence it is de-serialized. If not InvalidClassException exception is thrown. The only way to get rid of the InvalidClassException is to recompile and deploy the application again.

A serialVersionUID field can be declared explicitly by a Serliazable class, it must be static, final, and of type long.

How can we obtain the serialVersionUID for java classes which implement the Serializable interface?

serialver is a command which can be used to obtain the serialVersionUID for one or more java classes.

What are the compatible changes and incompatible changes in Java Serialization Mechanism?

Compatible changes are adding new fields, changing a field from static to non-static or a transient field to non-transient, adding classes to the object tree
Incompatible changes are deleting the existing fields, changing the class hierarchy, changing a non-static field to static, or non-transient to transient, changing the type of a primitive field.
If we explicitly mention the suid, then if any of the mentioned compatible changes are made the class need not be recompiled. But for incompatible changes, there is no other way than to compile again.

ALSO READ: Serialization of Singleton class..

What is the Difference between Externalizable and Serializable Interfaces?

Externalizable extend java.io.Serializable. It is used to change the JVM's default serialization behavior.

Serializable is a marker interface, therefore, we are not forced to implement any methods, however, Externalizable contains two methods readExternal() and writeExternal() which must be implemented.

If Serializable is used, Constructor is not called during de-serialization. While in the case of Externalizable, Constructor is called during de-serialization.

A serializable interface provides an inbuilt serialization mechanism to us which can be inefficient at times. However Externalizable interface is designed to give us greater control over the serialization mechanism. The readExternal() and writeExternal() methods provide us immense opportunity to enhance the performance of specific object serialization based on application needs.

One can drastically improve the application performance by implementing the Externalizable interface correctly. However there is also a chance that you may not write the best implementation, so if you are not really sure about the best way to serialize stick to the default implementation using a Serializable interface.

For example, when we have a big Java object with hundreds of attributes and we want to serialize only a dozen dynamically selected attributes to keep the state of the object we should use the Externalizable interface writeExternal method to selectively serialize the chosen attributes.

In case we have small objects and we know that most or all attributes are required to be serialized then we should be fine with using a Serializable interface and use of transient variables as appropriate.

Serialization using Serializable Interface
OutputStream fout = new FileOutputStream("ser.txt");
ObjectOutput oout = new ObjectOutputStream(fout);
System.out.println("Serialization process has started, serializing employee objects...");
oout.writeObject(object1);


DeSerialization using Serializable Interface
InputStream fin=new FileInputStream("ser.txt");
ObjectInput oin=new ObjectInputStream(fin);
System.out.println("DeSerialization process has started, displaying employee objects...");
Employee emp;
emp=(Employee)oin.readObject();


Serialization using Externalizable  Interface
public void writeExternal(ObjectOutput oo) throws IOException {
oo.writeInt(id);
oo.writeObject(name);
}

DeSerialization using Externalizable  Interface
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.id=in.readInt();
this.name=(String)in.readObject();
}

What if Serialization is not available, is any other alternative way to transfer objects over the network?

We can convert JSON to transfer the object. JSON is helpful in stringifying and de-stringifying objects.

Hibernate (ORM tool) helps in persisting objects in a database and later we can read persisted objects.

We can also convert objects into XML (as done in web services) and transfer objects over a network.

Is the constructor of the class called during DeSerialization process?

It depends on whether our object has implemented Serializable or Externalizable. 

If Serializable has been implemented - the constructor is not called during de-serialization process. But, if Externalizable has been implemented - the constructor is called during de-serialization process.

Is the constructor of a superclass called during DeSerialization process of subclass?

Again it depends on whether the superclass has implemented Serializable or not.

If superclass has implemented Serializable - the constructor is not called during DeSerialization process. Else if the superclass has not implemented Serializable - the constructor is called during DeSerialization process.

How can a subclass avoid Serialization if its superclass has implemented Serialization interface?

If superclass has implemented Serializable that means subclass is also Serializable (as subclass always inherits all features from its parent class), for avoiding Serialization in sub-class we can define writeObject() method and throw NotSerializableException(). e.g :

private void writeObject(ObjectOutputStream os) throws NotSerializableException {
throw new NotSerializableException("This class cannot be Serialized");
}

What will happen if one of the members of the class doesn't implement Serializable interface?

If we try to serialize an object of a class that implements Serializable, but the object includes a reference to a non- Serializable class then a ‘NotSerializableException’ will be thrown at runtime.

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

Java serialization process only continues in object hierarchy till the class is Serializable i.e. implements Serializable interface in Java and values of the instance variables inherited from superclass will be initialized by calling the constructor of Non-Serializable Super class during deserialization process. Once the constructor chaining will start it wouldn't be possible to stop that, hence even if classes higher in hierarchy implement a Serializable interface, their constructor will be executed.

Which kind of variables is not serialized during Java Serialization?

The answer is static and transient. The static variables belong to the class are not part of the state of the object so they are not saved as part of the serialized object. Also, Transient variables are also not included in the java serialization process.

Why static variables are not serialized?

Saving static variables with each serialized object would have the following problems. 
  • It will make a redundant copy of the 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 the current value.

What will be the value of the transient variable after de-serialization?

It’s the default value. e.g. if the transient variable is an int, its value after deserialization will be zero.

Can we Customize the Serialization process? Can we override the default Serialization process in Java?

Yes we can. During the Serialization, ObjectOutputStream.writeObject(object) and during Deserialization ObjectInputStream.readObject() is invoked.

We can define these two methods in our class, after which JVM will invoke these two methods instead of applying the default serialization mechanism. We need to make these methods private to avoid being inherited, overridden, or overloaded.

How to Serialize a collection in java? What will happen if we have used List, Set, and Map as members of the class that need to be serialized?

All standard implementations of collections List, Set and Map interface already implement java.io.Serializable. All the commonly used collection classes like java.util.ArrayList, java.util.Vector, java.util.Hashmap, java.util.Hashtable, java.util.HashSet, java.util.TreeSet also implements Serializable. This means we do not really need to write anything specific to serialize collection objects. However, we should keep the following things in mind before you serialize a collection object:
  • Make sure all the objects added in the collection are Serializable. 
  • Serializing the collection can be costly therefore make sure to serialize only required data instead of serializing the whole collection. 
  • In case you are using a custom implementation of the Collection interface then you may need to implement serialization for it.
ALSO CHECKCore Java Interview Questions And Answers

If you enjoy our content and want to support us, please consider donating via gpay, phonepay or paytm on +91 9920600280. Also, I’d appreciate it if you’d buy me a coffee☕ 


Keep learning and growing!
-K Himaanshu Shuklaa..

No comments:

Post a Comment