How To Deep Clone An Object Using Java In Memory Serialization
Tags: java, serialization, cloning
Published: 2019-08-24 09:38:14

In my previous articles, I had explained the [difference between deep and shallow cloning](https://www.programmingmitra.com/2016/11/Java-Cloning-Types-of-Cloning-Shallow-Deep-in-Details-with-Example.html) and [how copy-constructors](https://www.programmingmitra.com/2017/01/Java-cloning-copy-constructor-versus-Object-clone-or-cloning.html) and [defensive copy methods](https://www.programmingmitra.com/2017/01/java-cloning-why-copy-constructors-are-not-sufficient-or-good.html) are better than default java cloning.  
  
[Java object cloning](https://www.programmingmitra.com/2016/11/Java-Cloning-Types-of-Cloning-Shallow-Deep-in-Details-with-Example.html) using [copy constructors](https://www.programmingmitra.com/2017/01/Java-cloning-copy-constructor-versus-Object-clone-or-cloning.html) and [defensive copy methods](https://www.programmingmitra.com/2017/01/java-cloning-why-copy-constructors-are-not-sufficient-or-good.html) certainly have some advantages but we have to explicitly write some code to achieve deep cloning in all these approaches. And still, there are chances that we might miss something and do not get deeply cloned object.  
  
And as discussed in [5 different ways to create objects in java](https://www.programmingmitra.com/2016/05/different-ways-to-create-objects-in-java-with-example.html), deserialising a serialised object creates a new object with the same state as in the serialized object. So similar to above cloning approaches we can achieve deep cloning functionality using object [serialization and deserialization](https://www.programmingmitra.com/2019/08/what-is-serialization-everything-about-java-serialization-explained-with-example.html) as well and with this approach we do not have worry about or write code for deep cloning, we get it by default.  
  
However, cloning an object using serialization comes with some performance overhead and we can improve on it by using **in-memory serialization** if we just need to clone the object and don’t need to persist it in a file for future use.

  
  
We will use below `Employee` class as an example which has `name`, `doj` and `skills` as the state, for deep cloning we do not need to worry about the code>name field because it is a String object and by default all [strings are immutable in nature](https://www.programmingmitra.com/2018/02/why-string-is-immutable-and-final-in-java.html).  
  

> You can read more about immutability on [How to Create an Immutable Class in Java](https://www.programmingmitra.com/2018/02/how-to-create-immutable-class-in-java.html) and [Why String is Immutable and Final](https://www.programmingmitra.com/2018/02/why-string-is-immutable-and-final-in-java.html).

  

    class Employee implements Serializable {
        private static final long serialVersionUID = 2L;
    
        private String name;
        private LocalDate doj;
        private List<String> skills;
    
        public Employee(String name, LocalDate doj, List<String> skills) {
            this.name = name;
            this.doj = doj;
            this.skills = skills;
        }
    
        public String getName() { return name; }
        public LocalDate getDoj() { return doj; }
        public List<String> getSkills() { return skills; }
    
        // Method to deep clone a object using in memory serialization
        public Employee deepClone() throws IOException, ClassNotFoundException {
            // First serializing the object and its state to memory using ByteArrayOutputStream instead of FileOutputStream.
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);
            out.writeObject(this);
    
            // And then deserializing it from memory using ByteArrayOutputStream instead of FileInputStream.
            // Deserialization process will create a new object with the same state as in the serialized object,
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream in = new ObjectInputStream(bis);
            return (Employee) in.readObject();
        }
    
        @Override
        public String toString() {
            return String.format("Employee{name='%s', doj=%s, skills=%s}", name, doj, skills);
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            Employee employee = (Employee) o;
    
            return Objects.equals(name, employee.name) &&
                Objects.equals(doj, employee.doj) &&
                Objects.equals(skills, employee.skills);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name, doj, skills);
        }
    }
    

  
  
To deep clone an object of `Employee` class I have provided a `deepClone()` method which serializes the object to memory by using `ByteArrayOutputStream` instead of the `FileOutputStream` and deserialises it back using `ByteArrayInputStream` instead of the `FileInputStream`. Here we are serializing the object into bytes and deserializing it from bytes to object again.  
  

[![How To Deep Clone An Object Using Java In Memory Serialization](https://1.bp.blogspot.com/-mVY5K1h2smA/XVj7JdqZxGI/AAAAAAAAVzI/rCOaiHV5znMf1KmTgLdmySVTV8amaPEKACLcBGAs/s1600/Java-Deep-Cloning-Using-Serialization.png "How To Deep Clone An Object Using Java In Memory Serialization")](https://1.bp.blogspot.com/-mVY5K1h2smA/XVj7JdqZxGI/AAAAAAAAVzI/rCOaiHV5znMf1KmTgLdmySVTV8amaPEKACLcBGAs/s1600/Java-Deep-Cloning-Using-Serialization.png)

  
  
  
Employee class implements `Serializable` interface to achieve serialization which has its own disadvantages and we can overcome some of these disadvantages by [customizing the serialization process by using Externalizable interface](https://www.programmingmitra.com/2019/08/how-to-customize-serialization-in-java-by-using-externalizable-interface.html).  
  
We can run below tests to see if our cloning approach is deep or just shallow, here all `==` operations will return false (because both objects are separate) and all `equals` will return true (because both have the same content).  
  

    public static void main(String[] args) throws IOException, ClassNotFoundException {
     Employee emp = new Employee("Naresh Joshi", LocalDate.now(), Arrays.asList("Java", "Scala", "Spring"));
     System.out.println("Employee object: " + emp);
    
     // Deep cloning `emp` object by using our `deepClone` method.
     Employee clonedEmp = emp.deepClone();
     System.out.println("Cloned employee object: " + clonedEmp);
    
     System.out.println();
    
     // All of this will print false because both objects are separate.
     System.out.println(emp == clonedEmp);
     System.out.println(emp.getDoj() == clonedEmp.getDoj());
     System.out.println(emp.getSkills() == clonedEmp.getSkills());
    
     System.out.println();
    
     // All of this will print true because `clonedEmp` is a deep clone of `emp` and both have the same content.
     System.out.println(Objects.equals(emp, clonedEmp));
     System.out.println(Objects.equals(emp.getDoj(), clonedEmp.getDoj()));
     System.out.println(Objects.equals(emp.getSkills(), clonedEmp.getSkills()));
    }
    

  
We know deserialization process creates a new object every time which is not good if we have to make our class singleton. And that's why we need to override and disable serialization for our singleton class which we can achieve by providing writeReplace and readResolve methods.  
  
Similar to serialization, Java cloning also does not play along with singleton pattern, and that's why we need to override and disable it as well. We can do that by implementinng cloning in way so that it will either throw `CloneNotSupportedException` or return the same instance everytime.

  
  

> You can read more about Java cloning and serialization on [Java Cloning](https://www.programmingmitra.com/search/label/Java%20Cloning) and [Java Serialization](https://www.programmingmitra.com/search/label/Serialization) topics.

  
You can find the complete source code for this article on this [Github Repository](https://github.com/njnareshjoshi/exercises/blob/master/src/org/programming/mitra/exercises/DeepCloningUsingSerializationExample.java) and please feel free to provide your valuable feedback.