Copy Constructor
When you book a return train trip, the return ticket starts as a copy of the onward one: same passengers, same class, different date. Change the return date, and the onward ticket must stay as it was. A copy constructor creates a new object from an existing one of the same class, and the important part is making sure the copy is truly independent.
A Simple Copy Constructor
public class Tickets {
static class Ticket {
String from;
String to;
String date;
Ticket(String from, String to, String date) {
this.from = from;
this.to = to;
this.date = date;
}
Ticket(Ticket other) {
this.from = other.to;
this.to = other.from;
this.date = other.date;
}
String show() { return from + " -> " + to + " on " + date; }
}
public static void main(String[] args) {
Ticket onward = new Ticket("Hyderabad", "Pune", "2026-12-01");
Ticket back = new Ticket(onward);
back.date = "2026-12-05";
System.out.println(onward.show());
System.out.println(back.show());
}
}Hyderabad -> Pune on 2026-12-01
Pune -> Hyderabad on 2026-12-05How it works
- Lines 13 to 17: a copy constructor takes another object of the same class as its parameter and copies what it needs from it. Here it also swaps
fromandto, because it's building a return trip. - Line 24 creates a new object;
backandonwardare different objects. - Changing
back.dateleavesonwarduntouched.
Try it yourself: print onward == back. Then write a plain copy constructor that copies all three fields unchanged.
Shallow vs Deep Copy
Copying fields one by one is enough for primitives and for immutable objects like String. But if a field refers to a mutable object, such as an array or a list, copying the reference makes both objects share it:
public class Coaches {
static class Coach {
String code;
boolean[] booked;
Coach(String c, int n) { code = c; booked = new boolean[n]; }
Coach(Coach other) {
this.code = other.code;
this.booked = other.booked.clone();
}
}
public static void main(String[] args) {
Coach original = new Coach("S4", 4);
Coach copy = new Coach(original);
copy.booked[0] = true;
System.out.println("original seat 1 booked: " + original.booked[0]);
System.out.println("copy seat 1 booked: " + copy.booked[0]);
}
}public class CoachesShallow {
static class Coach {
String code;
boolean[] booked;
Coach(String c, int n) { code = c; booked = new boolean[n]; }
Coach(Coach other) {
this.code = other.code;
this.booked = other.booked; // shares the same array
}
}
public static void main(String[] args) {
Coach original = new Coach("S4", 4);
Coach copy = new Coach(original);
copy.booked[0] = true;
// the next line prints true!
System.out.println("original seat 1 booked: " + original.booked[0]);
System.out.println("copy seat 1 booked: " + copy.booked[0]);
}
}original seat 1 booked: false
copy seat 1 booked: trueThe deep version (line 10) copies the array with clone(), so each coach has its own. In the shallow version, booking a seat in the copy would also book it in the original, a nasty bug to track down.
Why Not clone()?
| Copy constructor | clone() | |
|---|---|---|
Needs Cloneable | No | Yes |
| Runs a constructor (validation) | Yes | No |
Can copy into final fields | Yes | Awkward |
| Return type | The right type, no cast | Object unless overridden |
| Clear about deep vs shallow | You write exactly what's copied | Shallow by default |
Most Java style guides, including Effective Java, recommend copy constructors or static copy factories (such as List.copyOf) over clone().
Common Mistakes
Copying references to arrays and lists. That's a shallow copy; the objects stay linked.
Forgetting a new field. When you add a field to the class, update the copy constructor too.
Accepting null. new Coach(null) throws a NullPointerException on other.code; check for it if null is possible.
Interview Corner
What is a copy constructor?
A constructor that takes an object of the same class and initializes the new object from it. Java doesn't create one automatically; you write it. It's usually preferred over clone(), because it runs normal constructor logic and lets you control exactly what is copied.
What is the difference between a shallow copy and a deep copy?
A shallow copy copies field values, so reference fields in both objects point to the same inner objects. A deep copy also copies the mutable inner objects, so the two objects are fully independent.
Practice
- Easy: Write a copy constructor for a
Studentclass withnameandrollNo. - Harder: Add an
int[] marksfield toStudentand make the copy constructor a deep copy. Prove it by changing a mark in the copy.
Key Takeaways
Was this tutorial helpful?