Java Notes
Learn object cloning in Java — the Cloneable interface, shallow copy vs deep copy, the clone() method, CloneNotSupportedException, and copy constructors as a safer alternative.
Cloning means creating a copy of an existing object — a new object in memory with the same field values. You need this when you want to modify an object without affecting the original.
Without cloning, assigning one object to another variable just copies the reference — both variables point to the same object.
// This does NOT create a copy
Student s1 = new Student("Asha", 88);
Student s2 = s1; // both point to same object
s2.marks = 50;
System.out.println(s1.marks); // 50 — s1 also changed!Cloning creates a genuinely separate object.
The Cloneable Interface
To use Java's built-in clone() method, a class must:
- Implement the
Cloneableinterface (marker interface — no methods to write) - Override
clone()and make itpublic
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Line by line:
implements Cloneable— signals to JVM that this class allows cloning.super.clone()— callsObject.clone()which does a bitwise copy of all fields.(Student)— cast becauseObject.clone()returnsObject.- After
clone(),copyis a separate object. Changingcopy.namedoes not affectoriginal.
Shallow Copy — The Default
Object.clone() creates a shallow copy. For primitive fields and String fields, this works perfectly. But for fields that are object references, the copy shares the same referenced object — it does not copy it.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
p2.name is a separate String — changing it does not affect p1. But p2.address is the same Address object as p1.address. Changing p2.address.city changes p1's city too. This is shallow copy.
Deep Copy — Copying Everything
A deep copy also clones any objects referenced by the fields. You must do this manually.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Line by line:
copy.address = this.address.clone();— this clones theAddressobject separately. Nowp2.addressandp1.addressare different objects.- Changing
p2.address.cityonly affects p2's address.
Copy Constructor — Simpler and Safer
Many Java developers prefer a copy constructor over clone(). It is simpler, cleaner, and does not require Cloneable or exception handling.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
new Rectangle(r1) creates a fresh copy. Scaling r2 does not affect r1. No interfaces, no exceptions.
Shallow vs Deep — Quick Summary
| Shallow Copy | Deep Copy | |
|---|---|---|
| Primitive fields | Copied correctly | Copied correctly |
| String fields | Effectively copied (Strings are immutable) | Copied correctly |
| Object reference fields | Shared — both objects point to the same nested object | Separate — nested object is also cloned |
| Achieved by | super.clone() | Manual: clone each nested object |
Common Mistake 1: Using clone() Without implements Cloneable
public class Item {
// Forgot: implements Cloneable
@Override
public Item clone() {
try {
return (Item) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e); // will always throw!
}
}
}super.clone() throws CloneNotSupportedException if the class does not implement Cloneable. Always add implements Cloneable.
Common Mistake 2: Shallow Copy When You Need Deep
public class Order {
String id;
List<String> items; // mutable — needs deep copy
@Override
public Order clone() {
try {
Order copy = (Order) super.clone();
// Shallow — copy and original share the same items list
// Changes to copy.items will affect original!
return copy;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}Whenever an object has a field that is a mutable reference type (List, Map, another custom object), shallow copy is not enough.
Practice Task
Task: Create a class Config with fields host (String) and port (int). Write a copy constructor. In main, create c1 with host "localhost" and port 8080. Create c2 as a copy. Change c2.host to "example.com" and c2.port to 443. Print both to verify c1 was not changed.
Hint: The copy constructor takes a Config parameter and copies each field. Changing c2.host will not affect c1 because Strings are immutable.
Solution:
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
What to observe: c1.host stays "localhost" after you change c2.host. Now modify the class to add a List<String> tags field. Use new ArrayList<>(other.tags) in the copy constructor. Change a tag in c2.tags — verify c1.tags is unaffected. That is the difference between shallow and deep copy in practice.
Continue the lesson path