Understanding Shallow Clone vs Deep Clone in Java

Object Cloning in Java

Object cloning creates a new instance and copies field values from the original. This functionality becomes essential when you need independent copies of mutable objects. Java provides two distinct cloning strategies: shallow clone and deep clone.

Shallow Clone

Shallow cloning creates a new object and copies all primitive fields along with references to nested objects. However, the cloned object shares the same reference pointers as the original for any non-primitive fields. Modifying a shared reference in one object affects the other.

public class Person implements Cloneable {
    private String name;
    private Address address;
    
    @Override
    protected Person clone() {
        try {
            return (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}

When calling clone(), the Address object inside the new Person instance points to the same memory location as the original. Changing address.setCity("Paris") on one instance modifies both.

Deep Clone

Deep cloning recursively copies all fields, creating entirely new reference objects for nested content. Each nested object gets instantiated independently, resulting in a completely disconnected object graph.

public class Person implements Serializable {
    private String name;
    private Address address;
    
    public Person deepClone() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (Person) ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Serialization-based cloning traverses the entire object graph and reconstructs every nested object as a separate instance. Alternatively, you can implement deep clone by manually instantiating and copying each field.

Choosing Between Shallow and Deep Clone

Scenario Approach
Only primitive fields Shallow clone suffices
Nested objects shouldn't be shared Deep clone required
Performance-critical with large object graphs Consider copy constructors
Immutable nested objects Shallow clone works fine

Practical Considerations

The Cloneable interface in Java is somewhat flawed—it's a marker interface with no methods. The clone() method lives in Object and performs a memberwise copy by default. For immutable fields or primitives, this works as expected.

When designing classes that require cloning, prefer immutable objects where possible. If mutable nested objects exist, explicitly document whether shallow or deep cloning behavior is expected. The copy constructor pattern often provides clearer semantics than implementing Cloneable.

Deep cloning through serialization requires all nested objects to implement Serializable. For complex object graphs with circular references, serialization may fail or produce unexpected results, making manual copy constructors the safer choice in such cases.

Tags: java clone object-oriented design-patterns memory-management

Posted on Tue, 08 Sep 2026 16:23:09 +0000 by clairence