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, andbooleanstore their actual values. - Object variables such as
DummyBean,StringBuilder, andArrayListstore 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.
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();
System.out.println(dum.getDummy());
System.out.println(dumtwo.getDummy());
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:
new DummyBean()creates the first object.dumrefers to it.dum.setDummy("foo")stores"foo"in that first object.new DummyBean(dum)creates a secondDummyBeanobject.- The copy constructor reads
dum's currentdummyvalue and assigns it to the new object. dumtworefers to the second object, not the first one.dum.setDummy("bar")changes only the first object.- The output is:
bar
foo
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.
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.
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
Comparisons
| Approach | Creates a new outer object? | Nested mutable objects independent? | Typical use |
|---|---|---|---|
dumtwo = dum | No | No | Intentionally share one object |
| Copy constructor with field assignment | Yes | Depends on fields copied | Most domain classes |
| Shallow copy | Yes | No, nested references are shared | Fields are primitives or immutable objects |
| Deep copy | Yes | Yes | Independent snapshots of mutable object graphs |
clone() | Usually | Usually no by default | Legacy 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.
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
copyOfoverclone()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.
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
- Create a
UserProfileclass withname,city, andtagsfields. - Add a copy constructor that accepts another
UserProfile. - Ensure the copied
tagslist is independent from the original list. - Create an original profile and an editable draft.
- Change the draft name and tags, then print both profiles.
Keep learning
Related questions
Add External JAR Files to an IntelliJ IDEA Java Project
Learn how to add external JAR dependencies to an IntelliJ IDEA Java project using module libraries, and when to use Maven or Gradle instead.
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Call a Method After a Delay in Android Java
Learn how to run Java code after a delay in Android using Handler.postDelayed, manage the main thread, and cancel callbacks safely.