Java Serialization & Deserialization
Java Serialization & Deserialization
Should Know
It's the process of converting an object into a byte stream for storage or transmission.
It's a marker interface that indicates a class can be serialized. It contains no methods to
implement.
It's a version identifier that helps ensure compatibility between serialized objects and their
classes. If not explicitly defined, Java generates one based on class structure, which can cause
incompatibility issues during class evolution.
The subclass can be serialized, but the superclass's fields won't be serialized unless the
subclass writes and reads them manually in writeObject() and readObject() methods.
The superclass must have a no-arg constructor.
It marks fields that should be excluded from serialization, typically for security reasons or when
fields contain non-serializable types.
Static fields are not serialized because they belong to the class, not to individual objects.
If the serialVersionUID matches but class structure has changed, deserialization may throw
InvalidClassException or the object might be partially initialized.
No, unless those references are marked transient or you implement custom serialization
methods.
Only the Serializable classes in the inheritance hierarchy are serialized. For non-serializable
superclasses, their fields are initialized using the no-arg constructor during deserialization.
It's a version identifier. If not declared, Java generates one based on class structure, which can
cause compatibility issues when the class evolves.
It represents all objects that are reachable from the object being serialized. The entire graph is
serialized unless references are marked transient.
16. How does serialization handle object references and cyclic
dependencies?
Java serialization is smart enough to handle object graphs with shared references and cycles.
When an object is first serialized, it's assigned a reference ID. If the same object appears again
in the object graph, only the reference ID is serialized instead of duplicating the object. This
preserves object identity and prevents infinite loops when deserializing cyclic references.
17. What issues can arise with inner classes and serialization?
Non-static inner classes maintain an implicit reference to their enclosing instance. This means
the outer class must also be serializable, or serialization will fail. Additionally, anonymous inner
classes and local inner classes have synthetic fields generated by the compiler that might cause
compatibility issues across different JVMs or compiler versions.
Serialization can be used for deep copying by serializing an object to a byte array stream and
then deserializing it:
java
public static <T> T deepCopy(T object) throws IOException,
ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.close();
return copy;
}
java
ObjectStreamClass descriptor = ObjectStreamClass.lookup(Employee.class);
● For a class to be serializable, all its superclasses must either be serializable or have a
no-arg constructor
● Fields from non-serializable superclasses are not automatically serialized
● During deserialization, non-serializable superclass constructors are executed
● Each class in the hierarchy can have its own readObject and writeObject methods
● If fields are added to a class: Deserialized objects will have default values for the new
fields
● If fields are removed: The values for removed fields are ignored during deserialization
● If field types change: Potential ClassCastException may occur
● Using explicit serialVersionUID helps manage these changes
The serialization proxy pattern is a way to provide a stable serialized form that's decoupled from
the actual class implementation:
java
public class RealClass implements Serializable {
private static final long serialVersionUID = 1L;
private int data;
SerializationProxy(RealClass real) {
this.data = real.data;
}
Methods are not part of serialization, so adding or removing methods doesn't directly affect
deserialization. However, if those methods affect the state representation or interact with
serialized fields, it may lead to logical errors or unexpected behavior.
● With Externalizable, you must explicitly save/restore all state including superclass state
● Externalizable requires a public no-arg constructor
● Externalizable provides complete control over the serialization format
● Performance is typically better with Externalizable as it avoids some reflection overhead
● The methods are writeExternal() and readExternal() vs writeObject() and
readObject()
Java 9 introduced ObjectInputFilter to validate incoming serialized data before object creation:
java
ObjectInputFilter filter = filterInfo -> {
Class<?> clazz = filterInfo.serialClass();
if (clazz != null) {
if (clazz.getName().startsWith("com.company.app")) {
return ObjectInputFilter.Status.ALLOWED;
}
}
return ObjectInputFilter.Status.REJECTED;
};