A Java deep clone (deep copy) example

Back when I was interviewing for computer programming positions in Boulder and Louisville, Colorado, I found that many interviewers ask questions about Java serialization. After being asked about serialization for the third time, I remembered an old Java deep clone hack that takes advantage of serialization.

The basic idea is:

  • You have a Java object, and you want to make a complete clone (copy) of it.
  • By marking your classes as being Serializable, you can write them out as an object stream, then read them back in as a different object.
  • When you read the object back in as a different object, this creates a deep clone of your original object.

A Java “deep clone” method

Getting right to the solution, the following method will let you make a deep clone of a Java object:

/**
 * This method makes a "deep clone" of any Java object it is given.
 * @author Alvin Alexander, https://alvinalexander.com
 */
 public static Object deepClone(Object object) {
   try {
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     ObjectOutputStream oos = new ObjectOutputStream(baos);
     oos.writeObject(object);
     ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
     ObjectInputStream ois = new ObjectInputStream(bais);
     return ois.readObject();
   }
   catch (Exception e) {
     e.printStackTrace();
     return null;
   }
 }

As you’ll see in the following example, you can call this method something like this:

// (1) create a Person object named Al
Address address = new Address("101 Fern Avenue", "Palmer", "Alaska");
Person al = new Person("Al", "Alexander", address);

// (2) make a deep clone of Al
Person neighbor = (Person)deepClone(al);

In this code, the neighbor object is a deep clone of the al object.

A complete deep clone example

If you’re in a hurry, I hope that code gave you what you need. But if it helps to see a complete “deep clone” example, here’s some Java source code that completely demonstrates this technique:

import java.io.*;

/**
 * Demonstrates a technique (a hack) to create a "deep clone"
 * in a Java application.
 * @author Alvin Alexander, https://alvinalexander.com
 */
public class JavaDeepClone {

  public static void main(String[] args) {
    // (1) create a Person object named Al
    Address address = new Address("101 Fern Avenue", "Palmer", "Alaska");
    Person al = new Person("Al", "Alexander", address);
    
    // (2) make a deep clone of Al
    Person neighbor = (Person)deepClone(al);
    
    // (3) modify the neighbor's attributes
    neighbor.firstName = "Martha";
    neighbor.lastName = "Stewart";
    
    // (4) show that it all worked
    System.out.print(neighbor);
  }

  /**
   * This method makes a "deep clone" of any object it is given.
   */
  public static Object deepClone(Object object) {
    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(object);
      ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
      ObjectInputStream ois = new ObjectInputStream(bais);
      return ois.readObject();
    }
    catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }
}

/**
 * These classes implement Serializable so we can write them out and 
 * read them back in as a stream of bytes.
 */
class Person implements Serializable {
  String firstName, lastName;
  Address address;
  public Person(String firstName, String lastName, Address address) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.address = address;
  }
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("First Name: " + firstName + "\n");
    sb.append("Last Name: " + lastName + "\n");
    sb.append("Street: " + address.street + "\n");
    return sb.toString();
  }
}

class Address implements Serializable {
  String street, city, state;
  public Address(String street, String city, String state) {
    this.street = street;
    this.city = city;
    this.state = state;
  }
}

I tried to document the Java source code pretty well, so I won’t describe it in any further detail here, other than to add these comments:

  • I didn’t create the Person and Address classes as Java beans, but only because I was trying to make this example as short as possible.
  • As you can see, the deepClone method does all the magic of making a copy/clone of your original object.

Summary: My Java deep clone example

As shown, this serialization technique/hack lets you easily make a deep clone of a Java object.

As far as I know, the only drawback to this technique is that it requires you to have your classes implement the Java Serializable interface, which is considered a “marker” interface, because it does not define any methods.

As a final note, I haven’t had the need to use this technique in a long time, so there may be better ways of doing this these days. But I can say that this technique worked well back in the day.