Serialization and Deserialization in Java
Complete Detailed Guide
Introduction
In Java, Serialization is the process of converting an object into a byte stream so it can be:
- Stored in a file
- Transmitted over a network
- Persisted for later use
Deserialization is the reverse process — converting the byte stream back into a copy of the original object.
Serialization and deserialization are fundamental for:
- Saving object states
- Transferring objects between JVMs
- Implementing caching and persistence
- Enabling remote communication in distributed systems
This blog explains serialization and deserialization in detail, with examples, use cases, limitations, and best practices.
Step 1 — Understanding Serialization
Serialization allows an object’s state to be saved and recreated later. Java provides the Serializable interface to mark a class as serializable.
Key Points:
- Serializable is a marker interface (no methods to implement).
- Only objects of classes implementing Serializable can be serialized.
- Static fields are not serialized (since they belong to the class, not the object instance).
- Transient fields are skipped during serialization.
Example of Serialization
Person Class:
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String password; // will not be serialized
public Person(String name, int age, String password) {
this.name = name;
this.age = age;
this.password = password;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", password='" + password + "'}";
}
}
Serialize Object:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class SerializeDemo {
public static void main(String[] args) {
Person person = new Person("John", 30, "secret123");
try (FileOutputStream fileOut = new FileOutputStream("person.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
out.writeObject(person);
System.out.println("Object has been serialized: " + person);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output Example:
Object has been serialized: Person{name='John', age=30, password='secret123'}
This creates a file person.ser containing the serialized byte stream of the object.
Step 2 — Understanding Deserialization
Deserialization recreates the original object from a byte stream stored in a file or received over a network.
Deserialize Object:
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class DeserializeDemo {
public static void main(String[] args) {
try (FileInputStream fileIn = new FileInputStream("person.ser");
ObjectInputStream in = new ObjectInputStream(fileIn)) {
Person person = (Person) in.readObject();
System.out.println("Object has been deserialized: " + person);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Expected Output:
Object has been deserialized: Person{name='John', age=30, password='null'}
Notice: The password field is null because it was marked transient.
Step 3 — serialVersionUID
serialVersionUID is a unique identifier for a serializable class.
It is used during deserialization to verify that the sender and receiver of a serialized object have compatible classes.
If serialVersionUID does not match, Java throws:
java.io.InvalidClassException
Example:
private static final long serialVersionUID = 1L;
Always define serialVersionUID to maintain version compatibility.
Step 4 — Customizing Serialization
Java provides two special methods for customization:
- private void writeObject(ObjectOutputStream out)
- private void readObject(ObjectInputStream in)
Example:
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(password); // manually serialize transient field
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
password = (String) in.readObject();
}
This allows:
- Controlling how fields are serialized.
- Encrypting sensitive data.
- Implementing custom logic during serialization/deserialization.
Step 5 — Externalizable Interface
Java also provides the Externalizable interface for complete control over serialization.
Key points:
- Requires implementing writeExternal(ObjectOutput out) and readExternal(ObjectInput in).
- No automatic serialization of fields — everything must be explicitly handled.
Example:
import java.io.*;
public class PersonExternal implements Externalizable {
private String name;
private int age;
public PersonExternal() {} // required
public PersonExternal(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(name);
out.writeInt(age);
}
@Override
public void readExternal(ObjectInput in) throws IOException {
name = in.readUTF();
age = in.readInt();
}
@Override
public String toString() {
return "PersonExternal{name='" + name + "', age=" + age + "}";
}
}
Advantages of Serialization
- Object Persistence: Allows saving object state to files or databases.
- Communication: Enables transferring objects over networks in distributed applications.
- Caching: Useful for caching objects.
- Deep Copy: Serialization can create deep copies of objects.
Disadvantages of Serialization
- Performance Overhead: Serialization/deserialization consumes CPU and memory.
- Security Risks: Serialized objects can be tampered with.
- Versioning Issues: Changes to classes require careful handling with serialVersionUID.
- Transient Fields: Not serialized unless explicitly handled.
Best Practices
- Always define serialVersionUID.
- Use transient for sensitive data.
- Use Externalizable for fine-grained control.
- Avoid unnecessary serialization to improve performance.
- Use custom serialization methods for security.
Real-World Use Cases
Serialization is widely used in:
- Java RMI (Remote Method Invocation) for remote object calls.
- Caching frameworks like Ehcache, Hazelcast.
- Message Brokers like Kafka (object messages).
- Persistence in file storage or databases.
- Session storage in web applications.
Summary
Serialization and deserialization in Java are powerful features that allow objects to be stored, transferred, and reconstructed.
By implementing the Serializable interface, Java developers can make objects persistent and transferable between different parts of an application or across JVMs.
However, serialization comes with overhead, security risks, and potential version compatibility issues that must be managed carefully.
Customizing serialization and using Externalizable gives developers fine control over how objects are saved and restored, making serialization a versatile tool in Java’s toolbox for persistence, communication, and caching.
