0
0
JavaHow-ToBeginner · 4 min read

How to Deep Clone Object in Java: Simple Guide and Example

To deep clone an object in Java, you can use serialization or implement a copy constructor that copies all nested objects. Deep cloning creates a new object with copies of all fields, not just references, ensuring changes to the clone don't affect the original.
📐

Syntax

Deep cloning in Java can be done mainly in two ways:

  • Using Serialization: The object is written to a byte stream and then read back to create a new object copy.
  • Using Copy Constructor: A constructor that takes an object of the same class and copies all fields deeply.

Both methods ensure nested objects are also cloned, not just the top-level object.

java
/* Using Serialization for deep clone */
public static <T> T deepClone(T object) {
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        oos.flush();
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return (T) ois.readObject();
    } catch (Exception e) {
        throw new RuntimeException("Deep clone failed", e);
    }
}
💻

Example

This example shows deep cloning using serialization. The Person class contains a nested Address object. After cloning, changing the clone's address does not affect the original.

java
import java.io.*;

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

class Person implements Serializable {
    String name;
    Address address;
    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }
}

public class DeepCloneExample {
    public static <T> T deepClone(T object) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            oos.flush();
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            return (T) ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException("Deep clone failed", e);
        }
    }

    public static void main(String[] args) {
        Person original = new Person("Alice", new Address("New York"));
        Person clone = deepClone(original);

        clone.address.city = "Los Angeles";

        System.out.println("Original city: " + original.address.city);
        System.out.println("Clone city: " + clone.address.city);
    }
}
Output
Original city: New York Clone city: Los Angeles
⚠️

Common Pitfalls

Common mistakes when deep cloning in Java include:

  • Using Object.clone() which performs a shallow copy by default, copying references instead of objects.
  • Not making nested objects Serializable when using serialization, causing runtime errors.
  • Forgetting to clone mutable nested objects in copy constructors, leading to shared references.

Always ensure all nested objects are properly cloned to avoid unexpected side effects.

java
/* Shallow clone example (wrong way) */
class ShallowPerson implements Cloneable {
    String name;
    Address address;
    public ShallowPerson(String name, Address address) {
        this.name = name;
        this.address = address;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone(); // shallow copy
    }
}

/* Correct deep clone with copy constructor */
class DeepPerson {
    String name;
    Address address;
    public DeepPerson(String name, Address address) {
        this.name = name;
        this.address = new Address(address.city); // deep copy
    }
}
📊

Quick Reference

Tips for deep cloning in Java:

  • Use serialization for quick deep cloning if all classes implement Serializable.
  • Implement copy constructors or factory methods for more control and better performance.
  • Override clone() carefully if you want to use it, ensuring deep copy of nested objects.
  • Remember deep cloning copies all nested objects, unlike shallow cloning which copies references.

Key Takeaways

Deep cloning creates a new object with copies of all nested objects, not just references.
Serialization is an easy way to deep clone if all objects implement Serializable.
Copy constructors give more control and avoid serialization overhead.
Shallow cloning copies references and can cause bugs if nested objects are mutable.
Always ensure nested objects are cloned to prevent shared state between original and clone.