Copy Constructor

Naveen AnamaneniUpdated · 5 min read

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

Tickets.java▶ Try it
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());
    }
}
Output
Hyderabad -> Pune on 2026-12-01
Pune -> Hyderabad on 2026-12-05

How it works

  1. 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 from and to, because it's building a return trip.
  2. Line 24 creates a new object; back and onward are different objects.
  3. Changing back.date leaves onward untouched.

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:

Shallow copies share inner objects; deep copies don't
Coaches.java▶ Try 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]);
    }
}
Output
original seat 1 booked: false
copy seat 1 booked:     true

The 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 constructorclone()
Needs CloneableNoYes
Runs a constructor (validation)YesNo
Can copy into final fieldsYesAwkward
Return typeThe right type, no castObject unless overridden
Clear about deep vs shallowYou write exactly what's copiedShallow 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

  1. Easy: Write a copy constructor for a Student class with name and rollNo.
  2. Harder: Add an int[] marks field to Student and make the copy constructor a deep copy. Prove it by changing a mark in the copy.

Quick check: Copy constructor

4 questions
1What parameter does a copy constructor take?
2A copy constructor does this.booked = other.booked; for an array. What kind of copy is that?
3Is it safe to share a String field between the original and the copy?
4Does Java add a copy constructor automatically?

Key Takeaways

Was this tutorial helpful?

Lesson 102 of 482