Tuesday, 18 June 2019

Serialization | Java deep copy using in-memory serialization

Serialization is an alternative and easiest way of deep cloning (with some performance overhead). Java serialization involves serializing the object into bytes and from bytes to object again.

In Serialization, the whole object graph into a persistent store and read whole object graph back when needed. This is exactly what you want when you deep copy an object.

Note, when you deep copy through serialization, you should make sure that all classes in the object's graph are serializableOtherwise, java.io.NotSerializableException will be thrown.

It is advisable to use in-memory deep cloning whenever it is the only need and we don’t need to persist the object for future use.

1. Java deep cloning example
To demonstrate deep cloning, I have created a demo class named Employee. This has three variables i.e. firstName, lastName and addressList. I will add a deepCopy() instance level method to this class. Whenever invoked on an instance of Employee, it will return an exact clone/deep copy of that instance.

For deep cloning, we must first serialization and then deserialization. For serialization, ByteArrayOutputStream and ObjectOutputStream must be used. ByteArrayInputStream and ObjectInputStream must be used for deserialization.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;

    private String firstName;
    private String lastName;
    private List addressList;

    public Employee(String fName, String lName, String[] addresses) {
        this.firstName = fName;
        this.lastName = lName;
        this.addressList = new ArrayList<>(Arrays.asList(addresses));

    public Employee deepCopy() throws Exception {

        //Serialization of object
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);

        //De-serialization of object
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bis);
        Employee copied = (Employee) in.readObject();

        return copied;

    public String toString() {
        return String.format("%s, %s, Address: %s", firstName, lastName, addressList);

2. Test the deep cloning
Let’s test the class and create a deep copy of instance to verify if it works as expected.

public class InMemoryTest {

    public static void main(String[] args) throws Exception {

        String[] addresses = { "India", "Qatar" };

        //Create instance of serializable object
        Employee employee = new Employee("Awadhesh", "Dixit", addresses);

        // Verify the content

        // Now create a deep copy of it
        Employee deepCopiedInstance = employee.deepCopy();

        // Again verify the content

        if (deepCopiedInstance != employee) {
            System.out.println("Object is cloned");
Awadhesh, Dixit, Address: [India, Qatar]
Awadhesh, Dixit, Address: [India, Qatar]
Object is cloned

  • When you implement the deep cloning, the copied object may contain some other object its references are copied recursively in the deep copy. 
  • Cyclic dependencies will be a big problem while implementing a deep copy. It does implements deep copy implicitly and gracefully handling cyclic dependencies.

  • Serialization is more expensive than using object.clone().
  • Please also, remember that deep cloning is evil for singleton pattern. It makes possible of having multiple instances of singleton classes. 
  • Not all objects are serializable (transient variable cannot be cloned). 
  • Serialization is not simple to implement for the deep cloned object.

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...