Deep Dive into Java Object Copying: From Shallow to Deep Copy Implementation Strategies

Oct 21, 2025 · Programming · 25 views · 7.8

Keywords: Java Object Copying | Shallow Copy | Deep Copy | Copy Constructor | Cloneable Interface | Serialization Copy

Abstract: This article provides an in-depth exploration of object copying mechanisms in Java, detailing the differences between shallow and deep copies along with their implementation approaches. Through concrete code examples, it systematically introduces various copying strategies including copy constructors, Cloneable interface, and serialization, while comparing their respective advantages and disadvantages. Combining best practices, the article offers comprehensive solutions for object copying to help developers avoid common reference sharing pitfalls.

Fundamental Concepts of Object Copying

In Java programming, object copying is a fundamental yet error-prone operation. When developers use the assignment operator =, they are actually copying object references rather than creating new object instances. This approach causes multiple variables to point to the same memory address, where modifications to one variable affect all related variables.

Problem Scenario Analysis

Consider the following typical scenario: developers need to create an independent copy of an object, but simple assignment operations cannot achieve this goal. For example, in the DummyBean class, the assignment operation dumtwo = dum results in both variables referencing the same object. When modifying properties of dum, dumtwo is also affected, which is often not the expected behavior.

Implementation of Copy Constructors

Copy constructors provide a safe and reliable copying strategy. By defining a constructor that accepts an object of the same type as a parameter, all necessary fields can be explicitly copied. This method avoids the complexity of the Cloneable interface and provides clear control over copying logic.

public class DummyBean {
    private String dummy;
    
    public DummyBean() {}
    
    // Copy constructor
    public DummyBean(DummyBean another) {
        this.dummy = another.dummy;
    }
    
    public String getDummy() {
        return dummy;
    }
    
    public void setDummy(String dummy) {
        this.dummy = dummy;
    }
}

In-depth Analysis of Cloneable Interface

Java provides the Cloneable interface to support object copying, but this approach has several potential issues. First, the clone() method is protected in the Object class and requires subclasses to explicitly override it and make it public. Second, the default clone() implementation performs shallow copying, which may not meet requirements for objects containing reference type fields.

public class DummyBean implements Cloneable {
    private String dummy;
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    
    // Other methods omitted
}

Comparison Between Shallow and Deep Copy

Shallow copying only duplicates the object itself and its primitive type fields. For reference type fields, it copies the references rather than the referenced objects. Deep copying recursively duplicates all referenced objects, creating completely independent copies. The choice between these approaches depends on specific business requirements.

Implementation Strategies for Deep Copy

Implementing deep copy requires manual handling of all reference type field duplication. For complex object graphs, this may require recursive copying of all related objects. The following example demonstrates deep copy implementation:

public class ComplexBean implements Cloneable {
    private String name;
    private DummyBean dummyBean;
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        ComplexBean cloned = (ComplexBean) super.clone();
        // Deep copy referenced objects
        cloned.dummyBean = (DummyBean) this.dummyBean.clone();
        return cloned;
    }
}

Copying Through Serialization

Deep copying can be achieved through object serialization and deserialization, which doesn't rely on the Cloneable interface. However, this method requires all related classes to implement the Serializable interface and may impact performance.

import java.io.*;

public class SerializationCopy {
    public static <T extends Serializable> T deepCopy(T object) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            oos.close();
            
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            return (T) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException("Deep copy failed", e);
        }
    }
}

Application of Third-Party Libraries

Libraries such as Apache Commons Lang and BeanUtils provide convenient copying utilities. The SerializationUtils.clone() method implements deep copy based on serialization, while BeanUtils.copyProperties() can copy field values based on property names.

// Using Apache Commons Lang
import org.apache.commons.lang3.SerializationUtils;

DummyBean original = new DummyBean();
DummyBean copy = SerializationUtils.clone(original);

Best Practice Recommendations

When selecting object copying strategies, copy constructors should be prioritized as they offer the best controllability and readability. For simple objects, the Cloneable interface might suffice, but its limitations should be noted. In performance-critical scenarios, manually implemented deep copies typically outperform serialization-based approaches.

Performance and Security Considerations

Different copying methods vary in performance and memory usage. Shallow copying is usually the fastest but may not meet requirements. Deep copying, while safe, may introduce performance overhead. Serialization is the most universal approach but has the worst performance and requires exception handling.

Conclusion

Java object copying is a technical aspect that requires careful consideration. Developers should choose appropriate copying strategies based on specific needs, understand the pros and cons of various methods, and explicitly define copying semantics in code to avoid unexpected reference sharing issues.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.