deep serialization in java

deep serialization in java

Yes, when you serialize an object in Java, the serialization mechanism also serializes the references to other objects that are part of the object’s state. This means that if an object contains references to other objects, those referenced objects are also serialized, provided they are also serializable. This process is known as deep serialization.

deep serialization in java

How References Are Serialized

  • 1. Direct References: If an object has fields that are references to other objects, these referenced objects are serialized along with the original object.
  • 2. Nested References: If these referenced objects, in turn, have references to other objects, those objects are also serialized. This ensures that the entire object graph reachable from the root object is serialized.
  • 3. Handling Non-Serializable References: If any object in the reference chain is not serializable, the serialization process will fail, throwing a `NotSerializableException`.

Example

Let’s illustrate this with an example involving two classes, `Department` and `Employee`, where `Department` contains a reference to an `Employee`.

Step 1: Define the Classes
```java
import java.io.Serializable;

class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int id;
    
    public Employee(String name, int id) {
        this.name = name;
        this.id = id;
    }

    // Getters and Setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", id=" + id +
                '}';
    }
}

class Department implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Employee manager;
    
    public Department(String name, Employee manager) {
        this.name = name;
        this.manager = manager;
    }

    // Getters and Setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Employee getManager() {
        return manager;
    }

    public void setManager(Employee manager) {
        this.manager = manager;
    }

    @Override
    public String toString() {
        return "Department{" +
                "name='" + name + '\'' +
                ", manager=" + manager +
                '}';
    }
}
```

Step 2: Serialize the Department Object
```java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializeDemo {
    public static void main(String[] args) {
        Employee emp = new Employee("John Doe", 12345);
        Department dept = new Department("Engineering", emp);
        
        try (FileOutputStream fileOut = new FileOutputStream("department.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            out.writeObject(dept);
            System.out.println("Serialized data is saved in department.ser");
        } catch (IOException i) {
            i.printStackTrace();
        }
    }
}
```

Step 3: Deserialize the Department Object
```java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserializeDemo {
    public static void main(String[] args) {
        Department dept = null;
        
        try (FileInputStream fileIn = new FileInputStream("department.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            dept = (Department) in.readObject();
        } catch (IOException i) {
            i.printStackTrace();
            return;
        } catch (ClassNotFoundException c) {
            System.out.println("Department class not found");
            c.printStackTrace();
            return;
        }
        
        System.out.println("Deserialized Department...");
        System.out.println("Name: " + dept.getName());
        System.out.println("Manager: " + dept.getManager());
    }
}
```

Explanation

  • Serialization Process: When the `Department` object `dept` is serialized, the `Employee` object `emp` referenced by the `manager` field is also serialized because it is part of the `Department` object’s state.
  • Deserialization Process: During deserialization, both the `Department` object and the `Employee` object referenced by the `manager` field are restored.

Key Points

  • Serializable Interface: All objects referenced by a serializable object must themselves be serializable. If any referenced object is not serializable, a `NotSerializableException` will be thrown.
  • Deep Serialization: Serialization in Java captures the entire object graph, meaning it includes all objects reachable from the original object, ensuring a complete and accurate reconstruction during deserialization.
  • Transient Fields: Fields marked as `transient` are not serialized. This is useful for excluding certain fields from the serialization process, such as sensitive information or fields that can be reconstructed.

This mechanism allows Java to effectively serialize complex objects with nested references, preserving the integrity and structure of the entire object graph.