Question

How to Copy Objects in Java: References, Shallow Copies, and Deep Copies

javaobjectcopyclone

Question

Consider this Java code:

DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints "foo"

DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints "foo"

dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints "bar", but I expected "foo"

I want to create a copy of dum in dumtwo so that changing dum does not affect dumtwo. Does dumtwo = dum copy only the object reference? How can I create a fresh, independent copy of a Java object?

Short Answer

You will learn that assigning one object variable to another in Java copies the reference, not the object itself. You will also learn how to create independent copies using copy constructors, and when a shallow copy is sufficient versus when a deep copy is needed.

Concept

Java variables behave differently depending on what they store:

  • Primitive variables such as int, double, and boolean store their actual values.
  • Object variables such as DummyBean, StringBuilder, and ArrayList store a reference to an object.

When you write this:

DummyBean dumtwo = dum;

Java creates a second reference to the same DummyBean object. There is still only one object in memory, so changes made through either variable are visible through the other.

To make two independent objects, you must explicitly create a new object and copy the needed state into it. This is commonly done with a copy constructor.

Copying matters whenever you need to preserve a snapshot of data, prevent accidental shared changes, or safely pass mutable objects between parts of an application.

Mental Model

Think of an object as a house and an object variable as its street address.

DummyBean dumtwo = dum;

This does not build a second house. It writes the same address on a second piece of paper. Both dum and dumtwo lead to the same house, so repainting the house through one address is visible through the other.

A real copy creates a new house with the same initial contents. After that, changing one house does not change the other.

Take Quiz

Syntax and Examples

Object assignment copies a reference:

DummyBean dumtwo = dum;

To create a separate object, define a copy constructor:

public class DummyBean {
    private String dummy;

    public DummyBean() {
    }

    public DummyBean(DummyBean other) {
        this.dummy = other.dummy;
    }

    public String getDummy() {
        return dummy;
    }

    public void setDummy(String dummy) {
        this.dummy = dummy;
    }
}

Use it like this:

DummyBean dum = new DummyBean();
dum.setDummy("foo");

DummyBean dumtwo = new DummyBean(dum);

dum.setDummy("bar");

System.out.println(dum.getDummy());    // bar
System.out.println(dumtwo.getDummy()); // foo

new DummyBean(dum) creates a new DummyBean. The constructor copies the value from the original object into the new one.

In this example, String is safe to share because strings are immutable: a String object cannot be changed after it is created.

Step by Step Execution

Consider this complete example:

DummyBean dum = new DummyBean();
dum.setDummy("foo");

DummyBean dumtwo = new DummyBean(dum);
dum.setDummy("bar");

System.out.println(dum.getDummy());
System.out.println(dumtwo.getDummy());

Execution flow:

  1. new DummyBean() creates the first object. dum refers to it.
  2. dum.setDummy("foo") stores "foo" in that first object.
  3. new DummyBean(dum) creates a second DummyBean object.
  4. The copy constructor reads dum's current dummy value and assigns it to the new object.
  5. dumtwo refers to the second object, not the first one.
  6. dum.setDummy("bar") changes only the first object.
  7. The output is:
bar
foo

By contrast, with DummyBean dumtwo = dum, step 3 never creates a second object. Both variables refer to the first object.

Real World Use Cases

Copying objects is useful in many common situations:

  • Editing forms: Keep an original user profile while the user edits a separate draft. Canceling the form can discard the draft.
  • API data protection: Copy mutable input before storing it so later caller changes do not alter your internal state.
  • Undo functionality: Save independent snapshots of a document, drawing, or configuration.
  • Order and payment processing: Preserve the address, price, or tax information used when an order was placed.
  • Background processing: Give a worker an independent data snapshot instead of sharing mutable state with the request-handling thread.
  • Configuration objects: Start with default settings and create separate customized settings for each environment or customer.
Take Quiz

Real Codebase Usage

In real Java projects, copy constructors are often preferred because they are explicit and type-safe:

public class UserSettings {
    private boolean emailNotifications;
    private String theme;

    public UserSettings(UserSettings source) {
        this.emailNotifications = source.emailNotifications;
        this.theme = source.theme;
    }
}

A common defensive-copying pattern is used when a class receives or returns mutable collections:

import java.util.ArrayList;
import java.util.List;

public class Team {
    private final List<String> members;

    public Team(List<String> members) {
        this.members = new ArrayList<>(members);
    }

    public List<String> getMembers() {
        return new ArrayList<>(members);
    }
}

This prevents outside code from modifying the Team object's internal list directly.

For objects with nested mutable fields, developers copy each mutable field deliberately. For example, a List is copied with new ArrayList<>(sourceList), and each mutable element may also need copying. The required depth of copying depends on whether nested objects must be independent too.

Common Mistakes

Expecting assignment to duplicate an object

This shares one object:

DummyBean dumtwo = dum;

Use a constructor or factory that creates a new instance instead:

DummyBean dumtwo = new DummyBean(dum);

Copying a mutable nested reference accidentally

Suppose a class contains a mutable list:

public class Report {
    private List<String> tags;

    public Report(Report other) {
        this.tags = other.tags; // Problem: both reports share one list
    }
}

Changing tags in either report affects both. Copy the list:

public Report(Report other) {
    this.tags = new ArrayList<>(other.tags);
}

Assuming a shallow copy is always enough

Copying a list creates a new list, but it does not automatically copy the mutable objects inside it. If the elements themselves can change, copy those elements too.

Using clone() without understanding its behavior

Object.clone() commonly performs a shallow copy and requires special setup through Cloneable. It can be easy to implement incorrectly. For many application classes, a copy constructor or named copy method is clearer.

Forgetting to handle null

If a copy constructor accepts null, accessing its fields causes a NullPointerException. Either reject it clearly or define a behavior:

import java.util.Objects;

public DummyBean(DummyBean other) {
    Objects.requireNonNull(other, "other must not be null");
    this.dummy = other.dummy;
}

Comparisons

ApproachCreates a new outer object?Nested mutable objects independent?Typical use
dumtwo = dumNoNoIntentionally share one object
Copy constructor with field assignmentYesDepends on fields copiedMost domain classes
Shallow copyYesNo, nested references are sharedFields are primitives or immutable objects
Deep copyYesYesIndependent snapshots of mutable object graphs
clone()UsuallyUsually no by defaultLegacy APIs; use carefully

A shallow copy copies the outer object's fields. If a field is a reference to a mutable object, that reference is shared.

A deep copy creates copies of the nested mutable objects too. This prevents changes from crossing between the original and copy.

Take Quiz

Cheat Sheet

// Reference assignment: one object, two variables
DummyBean b = a;

// Independent outer object: copy constructor
DummyBean b = new DummyBean(a);
  • Object variables store references.
  • = does not automatically duplicate an object.
  • Use a copy constructor for clear, explicit copying.
  • Primitive values can be assigned directly in a copy constructor.
  • Immutable objects, such as String, can usually be shared safely.
  • Copy mutable collections with constructors such as new ArrayList<>(oldList).
  • For a deep copy, also copy each mutable nested object.
  • Prefer copy constructors or named methods such as copyOf over clone() for most application code.

FAQ

Does = copy an object in Java?

No. For objects, = copies the reference. Both variables then refer to the same object.

Why does changing dum also change dumtwo?

Because dum and dumtwo point to the same DummyBean after dumtwo = dum.

What is the simplest way to copy a Java object?

For your own classes, create a copy constructor such as new DummyBean(existingBean).

What is the difference between shallow copy and deep copy?

A shallow copy creates a new outer object but may share nested mutable objects. A deep copy also duplicates nested mutable objects.

Do I need to copy a String when copying an object?

Usually no. String is immutable, so it cannot be changed after creation.

Should I use clone() to copy Java objects?

Usually, a copy constructor or named copy method is easier to read and maintain. clone() can produce unexpected shallow copies.

How do I copy an ArrayList in Java?

Use new ArrayList<>(originalList). This creates a new list container but does not deep-copy its mutable elements.

Take Quiz

Mini Project

Description

Create a small profile editor that keeps an original profile and makes an editable copy. This models a common form workflow: a user can change a draft without changing the saved profile until they explicitly save it.

Goal

Create an independent profile copy, modify the draft, and verify that the original profile remains unchanged.

Requirements

  1. Create a UserProfile class with name, city, and tags fields.
  2. Add a copy constructor that accepts another UserProfile.
  3. Ensure the copied tags list is independent from the original list.
  4. Create an original profile and an editable draft.
  5. Change the draft name and tags, then print both profiles.
Take Quiz

Keep learning

Related questions

View more