Deep Copy vs Shallow Copy in Java

Deep Copy vs Shallow Copy in Java

I. Conceptual Description
Deep copy and shallow copy are two methods of object copying. A shallow copy only duplicates the object itself and its primitive-type fields, while reference-type fields still point to the original object's reference address. A deep copy recursively duplicates all objects pointed to by reference-type fields, creating a completely independent new object.

II. Shallow Copy Explained

  1. Implementation Method

    • Implement the Cloneable interface
    • Override the Object.clone() method (default is protected)
    • Call super.clone() to complete basic copying
  2. Code Example

class Person implements Cloneable {
    String name;
    Address address; // Reference-type field
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone(); // Shallow copy
    }
}
  1. Problem Demonstration
Person p1 = new Person("Tom", new Address("Beijing"));
Person p2 = (Person) p1.clone();
p2.address.city = "Shanghai"; // p1's address will also be modified!
System.out.println(p1.address.city); // Outputs "Shanghai"

III. Deep Copy Implementation Methods

  1. Manual Recursive Cloning
class Address implements Cloneable {
    String city;
    // Override clone method
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Person implements Cloneable {
    String name;
    Address address;
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        Person cloned = (Person) super.clone();
        cloned.address = (Address) this.address.clone(); // Key step
        return cloned;
    }
}
  1. Serialization Method
public class DeepCopyUtil {
    public static <T> T deepCopy(T obj) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (T) ois.readObject();
    }
}
// All involved classes must implement Serializable interface

IV. Comparison Summary

Feature Shallow Copy Deep Copy
Object Independence Partially independent Completely independent
Reference Type Handling Shares references Creates new objects
Performance Overhead Small Large (especially with serialization)
Implementation Complexity Simple Complex

V. Notes

  1. Circular Reference Issue: Deep copy needs to handle circular references between objects
  2. Performance Considerations: For complex object graphs, deep copy may incur significant overhead
  3. Recommended Solutions: Consider using immutable objects to avoid copy needs, or use copy constructors instead of the Cloneable interface

VI. Practical Application Scenarios

  • Shallow Copy: When configuration objects share basic settings
  • Deep Copy: When completely isolated context is needed (e.g., session replication, transaction rollback)