Shallow Copy vs Deep Copy in Java
Fast recall
Quick revision
Core answer
Object.clone() is shallow by default. Deep copy: copy constructor (preferred), or serialize/deserialize. Immutable fields (String, Integer, LocalDate) are always safe in shallow copy — they cannot be mutated through either reference.Whether the candidate understands that shallow copy duplicates references while deep copy duplicates the entire object graph — and can identify the bug that occurs when a shallow copy shares mutable internal state with the original
Assuming clone() produces a deep copy. Thinking that copying an array with Arrays.copyOf() is deep — it copies the array container but the elements inside are still shared references. Not realizing that immutable fields (String, Integer) don't need deep copying
Explain that copy constructors are the practical solution, not clone(). Mention serialization-based deep copy as a quick-and-dirty approach for complex graphs. Know that immutable objects make the shallow vs deep distinction irrelevant — if nothing can be mutated, sharing is safe
Interview-ready guide
Interview answer
Copying an object in Java is not the same as duplicating it — a shallow copy creates a new container but shares references to any mutable objects inside it, while a deep copy recursively creates independent instances of everything in the object graph.
Shallow copy — where the bug hides
- Primitives and immutable fields (
String,Integer,LocalDate) are safe — they're copied by value or can't be mutated - Mutable internals are the danger: shallow-copy an
Orderwith anArrayListand both the original and copy share the same list - Add an item through the copy — it appears in the original with no exception, just silent cross-contamination
Deep copy — options and trade-offs
- Copy constructor:
new Order(original)— explicit, type-safe, per-field control over what needs deep copying new ArrayList<>(original.items)creates a new list; ifItemis mutable, you need to copy those too- Serialization-based: serialize to bytes and deserialize — handles arbitrary nesting, but slow and requires
Serializable
The better answer is often immutability
- If internals are immutable, sharing references is harmless — the shallow vs deep distinction becomes irrelevant
- Defensive copies in constructors protect immutable classes from callers passing mutable objects in
Defensive copies in constructors:
- Use
List.copyOf(tags)in constructors for immutable classes — callers passing a mutable list can't mutate your internal state
I recommend copy constructors over clone(), and List.copyOf() for defensive copies in constructors.
Shallow Copy vs Deep Copy in Java
Direct Answer
Shallow copy: copies field values — mutable reference fields still shared (mutating one affects the other). Deep copy: recursively duplicates entire object graph — fully independent. Object.clone() is shallow by default. Deep copy: copy constructor (preferred), or serialize/deserialize. Immutable fields (String, Integer, LocalDate) are always safe in shallow copy — they cannot be mutated through either reference.
Common Mistakes & Pitfalls
Assuming clone() produces a deep copy. Thinking that copying an array with Arrays.copyOf() is deep — it copies the array container but the elements inside are still shared references. Not realizing that immutable fields (String, Integer) don't need deep copying
Check your understanding
Answer these without looking back at the article.
- Why does Arrays.copyOf() produce a shallow copy for an array of objects?
- If a class has only String and int fields, is shallow copy always safe — and why?
- How does serialization-based deep copy work and when would you use it over a copy constructor?
- What is the difference between a copy constructor and clone() in terms of safety and flexibility?
- How do defensive copies protect immutability — where in Java's standard library is this pattern used?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.