Object Serialization and Deserialization in Java: The Essentials
In the realm of Java programming, object serialization and deserialization are crucial concepts that every intermediate - to - advanced software engineer should master. Serialization is the process of converting an object’s state into a byte stream, which can then be stored in a file, sent over a network, or saved in a database. Deserialization, on the other hand, is the reverse process, where the byte stream is converted back into an object. This allows Java objects to be persisted across different environments and systems, enabling seamless data transfer and storage.
Table of Contents
- Core Concepts
- What is Serialization?
- What is Deserialization?
- The
SerializableInterface - The
ExternalizableInterface
- Typical Usage Scenarios
- Data Persistence
- Network Communication
- Caching
- Common Practices
- Versioning with
serialVersionUID - Transient Fields
- Custom Serialization and Deserialization
- Versioning with
- Conclusion
- FAQ
- References
Detailed and Structured Article
Core Concepts
What is Serialization?
Serialization is the mechanism of converting an object into a sequence of bytes. This process captures the state of the object, including the values of its fields, so that it can be reconstructed later. In Java, serialization is used to make objects persistent, which means that the object’s state can be saved and retrieved at a later time.
What is Deserialization?
Deserialization is the inverse operation of serialization. It takes a byte stream and reconstructs an object from it. When deserializing an object, Java uses the information stored in the byte stream to recreate the object’s state, including the values of its fields.
The Serializable Interface
In Java, to make an object serializable, the class of the object must implement the Serializable interface. This is a marker interface, which means it has no methods. It simply indicates to the Java serialization mechanism that objects of this class can be serialized.
import java.io.Serializable;
class Employee implements Serializable {
private String name;
private int id;
public Employee(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}
The Externalizable Interface
The Externalizable interface is another way to make an object serializable. Unlike the Serializable interface, Externalizable has two methods: writeExternal and readExternal. These methods allow the developer to have full control over the serialization and deserialization process.
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
class Student implements Externalizable {
private String name;
private int age;
public Student() {}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
out.writeInt(age);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
age = in.readInt();
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Typical Usage Scenarios
Data Persistence
One of the most common use cases of serialization is data persistence. For example, you can save the state of an application’s objects to a file. When the application is restarted, the objects can be deserialized from the file, restoring their previous state.
import java.io.*;
public class DataPersistenceExample {
public static void main(String[] args) {
Employee emp = new Employee("John", 123);
// Serialization
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("employee.ser"))) {
oos.writeObject(emp);
} catch (IOException e) {
e.printStackTrace();
}
// Deserialization
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("employee.ser"))) {
Employee deserializedEmp = (Employee) ois.readObject();
System.out.println("Name: " + deserializedEmp.getName() + ", ID: " + deserializedEmp.getId());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Network Communication
Serialization is also used in network communication. When objects need to be sent over a network, they are first serialized into a byte stream. The receiving end then deserializes the byte stream to recreate the objects.
Caching
In caching systems, serialization can be used to store objects in a cache. For example, in a distributed cache, objects can be serialized and stored in a cache server. When needed, the objects can be retrieved from the cache and deserialized.
Common Practices
Versioning with serialVersionUID
The serialVersionUID is a unique identifier for a serializable class. It is used to ensure that the class used during deserialization is compatible with the class used during serialization. If the serialVersionUID of the class changes between serialization and deserialization, a InvalidClassException will be thrown.
import java.io.Serializable;
class Customer implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int customerId;
public Customer(String name, int customerId) {
this.name = name;
this.customerId = customerId;
}
public String getName() {
return name;
}
public int getCustomerId() {
return customerId;
}
}
Transient Fields
The transient keyword can be used to mark a field as non - serializable. When an object is serialized, transient fields are not included in the byte stream. This is useful for fields that contain sensitive information or information that can be recalculated.
import java.io.Serializable;
class Account implements Serializable {
private String accountNumber;
private transient String password;
public Account(String accountNumber, String password) {
this.accountNumber = accountNumber;
this.password = password;
}
public String getAccountNumber() {
return accountNumber;
}
public String getPassword() {
return password;
}
}
Custom Serialization and Deserialization
You can also provide custom serialization and deserialization methods by implementing the writeObject and readObject methods in your class.
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Book implements Serializable {
private String title;
private int year;
public Book(String title, int year) {
this.title = title;
this.year = year;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(title);
out.writeInt(year + 1);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
title = (String) in.readObject();
year = in.readInt() - 1;
}
public String getTitle() {
return title;
}
public int getYear() {
return year;
}
}
Conclusion
Object serialization and deserialization in Java are powerful features that enable data persistence, network communication, and caching. By understanding the core concepts, typical usage scenarios, and common practices, intermediate - to - advanced software engineers can effectively use serialization and deserialization in their Java applications. However, it is important to be aware of potential issues such as versioning and security when using these features.
FAQ
Q1: What happens if a class implements Serializable but one of its fields is not serializable?
A: If a class implements Serializable but one of its fields is not serializable, a NotSerializableException will be thrown during serialization. You can mark the non - serializable field as transient to avoid this issue.
Q2: Can I serialize an object that has a reference to a non - serializable object?
A: If an object has a reference to a non - serializable object, the serialization will fail with a NotSerializableException unless the reference is marked as transient.
Q3: What is the difference between Serializable and Externalizable?
A: The Serializable interface is a marker interface, and Java takes care of the serialization and deserialization process. The Externalizable interface allows the developer to have full control over the serialization and deserialization process by implementing the writeExternal and readExternal methods.
References
- The Java Tutorials: https://docs.oracle.com/javase/tutorial/java/javaOO/serialization.html
- Effective Java by Joshua Bloch