Backend Development 8 min read

Deep Copy in Java: Multiple Implementation Methods

This article explains the difference between shallow and deep copying in Java and provides five practical techniques—including constructor copying, overriding clone(), Apache Commons Lang serialization, Gson serialization, and Jackson serialization—complete with code examples and test cases to demonstrate each approach.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Deep Copy in Java: Multiple Implementation Methods

In Java, shallow copy copies only object references while deep copy duplicates the entire object graph, preventing changes in the original from affecting the copy. The article first defines simple User and Address classes used throughout the examples.

Method 1: Constructor Copy – Create a new instance by passing primitive fields directly and constructing new nested objects for reference fields. Example test case shows that modifying the original address does not affect the copied object's address.

public class User {
    private String name;
    private Address address;
    // constructors, getters, setters omitted
}

public class Address {
    private String city;
    private String country;
    // constructors, getters, setters omitted
}

@Test
public void constructorCopy() {
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
    User copyUser = new User(user.getName(), new Address(address.getCity(), address.getCountry()));
    user.getAddress().setCity("深圳");
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
}

Method 2: Override clone() and Implement Cloneable – Override clone() to perform a shallow copy via super.clone() and then deep‑copy mutable fields manually.

public class Address implements Cloneable {
    private String city;
    private String country;
    @Override
    public Address clone() throws CloneNotSupportedException {
        return (Address) super.clone();
    }
}

public class User implements Cloneable {
    private String name;
    private Address address;
    @Override
    public User clone() throws CloneNotSupportedException {
        User user = (User) super.clone();
        user.setAddress(this.address.clone());
        return user;
    }
}

@Test
public void cloneCopy() throws CloneNotSupportedException {
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
    User copyUser = user.clone();
    user.getAddress().setCity("深圳");
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
}

Method 3: Apache Commons Lang Serialization – Use SerializationUtils.clone() to deep‑copy objects that implement Serializable .

public class Address implements Serializable { /* fields */ }
public class User implements Serializable { /* fields */ }

@Test
public void serializableCopy() {
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
    User copyUser = (User) SerializationUtils.clone(user);
    user.getAddress().setCity("深圳");
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
}

Method 4: Gson Serialization – Convert the object to JSON with Gson and back, achieving a deep copy without requiring Serializable .

@Test
public void gsonCopy() {
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
    Gson gson = new Gson();
    User copyUser = gson.fromJson(gson.toJson(user), User.class);
    user.getAddress().setCity("深圳");
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
}

Method 5: Jackson Serialization – Similar to Gson but requires a no‑argument constructor for the classes.

@Test
public void jacksonCopy() throws IOException {
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
    ObjectMapper mapper = new ObjectMapper();
    User copyUser = mapper.readValue(mapper.writeValueAsString(user), User.class);
    user.getAddress().setCity("深圳");
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
}

The article concludes by advising developers to choose the method that best fits their class design—whether they already provide a deep‑copy constructor, implement Cloneable , Serializable , or have a default constructor for JSON libraries.

JavaSerializationGsonJacksondeep copyclone
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.