Blog header background

Copy Constructor in Java – A Complete Guide with Examples

Updated on April 16, 2026

16 min read

Copy link
Share on WhatsApp

Understanding the copy constructor in java is essential for any Java developer working with object-oriented programming. A java copy constructor example shows how to create an independent duplicate of an existing object – controlling exactly which fields are copied and how nested objects are handled.

This guide covers all java constructor types, the complete copy constructor in java with example program, the crucial difference in shallow copy vs deep copy in java, java object cloning via the clone() method, and every approach to how to copy an object in java.

Java Constructor Types – A Quick Overview

Java constructor types determine how objects are initialised when they are first created. Java supports four primary java constructor types, each serving a distinct purpose. Understanding all four is the foundation for mastering the copy constructor.

Constructor Type

Description

When Used

Default Constructor

No-argument constructor provided by Java if none is defined – initialises fields to default values (0, null, false)

When no initialisation arguments are needed

Parameterised Constructor

Accepts arguments to initialise fields with specific values at creation time

When objects need custom initial state

Copy Constructor

Creates a new object by copying state from an existing object of the same class

When an independent duplicate of an object is needed

Private Constructor

Prevents external instantiation – used in Singleton and static utility classes

Design patterns: Singleton, Factory, Builder

Among all java constructor types, the copy constructor is the most nuanced – it requires understanding object references, memory layout, and the difference between shallow and deep copying to implement correctly.

brochure-banner-bg

POSTGRADUATE PROGRAM IN

Multi Cloud Architecture & DevOps

Master cloud architecture, DevOps practices, and automation to build scalable, resilient systems.

What is a Copy Constructor in Java?

A copy constructor in java is a special constructor that creates a new object by copying the field values from an existing object of the same class. It accepts an instance of the same class as its only parameter and initialises the new object with identical (or customised) state.

Property

Value

Parameter

Single argument – an object of the same class

Purpose

Create an independent copy of an existing object

Inheritance

Cannot be inherited – must be defined in each class/subclass

Access

Can access all fields (public, protected, private) of the passed object

Default provided?

No – Java does not auto-generate a copy constructor (unlike C++)

Primary use case

Deep copy in java – ensuring the copy is fully independent of the original

Key Concept: Java does NOT provide a copy constructor automatically. Unlike C++, which generates one by default, Java requires you to write it explicitly. This gives you full control over how copying behaves – especially critical for deep copy in java scenarios.

Basic Copy Constructor in Java – Example

// copy constructor in java with example program

public class Student {

private String name;

private int age;

// Parameterised constructor

public Student(String name, int age) {

this.name = name;

this.age = age;

}

// Copy constructor in java

public Student(Student s) {

this.name = s.name; // Copy primitive/immutable fields

this.age = s.age;

}

public void display() {

System.out.println("Name: " + name + ", Age: " + age);

}

public static void main(String[] args) {

Student original = new Student("Mohan", 15);

Student copy = new Student(original); // Copy constructor call

System.out.println("Original:"); original.display();

System.out.println("Copy:"); copy.display();

}

}

// Output:

// Original: Name: Mohan, Age: 15

// Copy: Name: Mohan, Age: 15

Types of Copy Constructors in Java

The two types of copy constructor in java – shallow and deep – differ in how they handle reference-type fields (arrays, objects nested inside the class).

1. Shallow Copy (Default Copy) Constructor

A shallow copy duplicates primitive fields by value but copies object reference fields by reference – meaning both the original and the copy point to the same nested objects in memory. Modifying a mutable nested object through the copy will also change the original.

// java copy constructor example - shallow copy

public class Person {

private String name;

private int age;

private int[] scores; // Reference type - array

public Person(String name, int age, int[] scores) {

this.name = name;

this.age = age;

this.scores = scores;

}

// Shallow copy constructor - copies array REFERENCE not content

public Person(Person p) {

this.name = p.name;

this.age = p.age;

this.scores = p.scores; // ← Both objects share the same array!

}

public static void main(String[] args) {

int[] scores = {85, 90, 95};

Person original = new Person("Mohan", 15, scores);

Person copy = new Person(original);

copy.scores[0] = 50; // Modifying copy's scores...

System.out.println(original.scores[0]); // Output: 50 ← PROBLEM!

// Original is affected because both share the same array reference

}

}

Key Concept: Shallow copy works correctly for primitive fields (int, double, boolean) and immutable objects (String – already immutable). It only causes problems with mutable reference types like arrays, ArrayLists, and custom objects.

2. Deep Copy Constructor

Deep copy in java creates completely independent copies of all fields – including nested objects and arrays. Modifying the copy never affects the original. This is the correct approach for mutable reference fields.

// copy constructor in java program - deep copy with nested object

public class Address {

String city;

String country;

public Address(String city, String country) {

this.city = city; this.country = country;

}

// Copy constructor for Address

public Address(Address a) {

this.city = a.city;

this.country = a.country;

}

}

public class Person {

private String name;

private int age;

private int[] scores; // Mutable array

private Address address; // Mutable nested object

public Person(String name, int age, int[] scores, Address address) {

this.name = name;

this.age = age;

this.scores = scores;

this.address = address;

}

// Deep copy constructor in java

public Person(Person p) {

this.name = p.name;

this.age = p.age;

this.scores = p.scores.clone(); // New independent array

this.address = new Address(p.address); // New independent object

}

public static void main(String[] args) {

int[] scores = {85, 90, 95};

Address addr = new Address("Delhi", "India");

Person original = new Person("Java", 45, scores, addr);

Person copy = new Person(original); // Deep copy

copy.scores[0] = 50;

copy.address.city = "Mumbai";

System.out.println(original.scores[0]); // 85 - UNCHANGED

System.out.println(original.address.city); // Delhi - UNCHANGED

System.out.println(copy.scores[0]); // 50

System.out.println(copy.address.city); // Mumbai

}

}

Shallow Copy vs Deep Copy in Java

Shallow copy vs deep copy in java is one of the most critical distinctions in Java object handling. Choosing the wrong approach leads to subtle, hard-to-debug bugs where modifying one object unexpectedly changes another.

Dimension

Shallow Copy

Deep Copy in Java

Primitive fields

Copied by value – fully independent

Copied by value – fully independent

Immutable fields (String)

Reference copied – safe (immutable objects can’t change)

Reference copied – also safe

Mutable reference fields

Reference copied – SHARED between original and copy

New object created – INDEPENDENT

Arrays

Reference to same array – dangerous

Array cloned or new array created – safe

Nested objects

Same nested object reference shared

Each nested object deep-copied recursively

Memory usage

Lower – fewer new objects created

Higher – all nested objects duplicated

Performance

Faster – no recursive copying

Slower – recursive duplication

Safety

Unsafe for mutable fields

Safe – modifications fully isolated

Java implementations

p1 = p2 (reference copy), Object.clone() default

Copy constructor (manual), serialisation trick

Side-by-Side: Shallow vs Deep Copy Behaviour

// shallow copy vs deep copy in java - side by side demonstration

import java.util.Arrays;

public class CopyDemo {

int[] data;

CopyDemo(int[] data) { this.data = data; }

// Shallow copy constructor

static CopyDemo shallowCopy(CopyDemo src) {

CopyDemo c = new CopyDemo(null);

c.data = src.data; // Copies reference

return c;

}

// Deep copy constructor

static CopyDemo deepCopy(CopyDemo src) {

CopyDemo c = new CopyDemo(null);

c.data = Arrays.copyOf(src.data, src.data.length); // New array

return c;

}

public static void main(String[] args) {

CopyDemo original = new CopyDemo(new int[]{1, 2, 3});

CopyDemo shallow = shallowCopy(original);

CopyDemo deep = deepCopy(original);

shallow.data[0] = 99; // Modifies original too!

deep.data[0] = 77; // Does NOT affect original

System.out.println(Arrays.toString(original.data));

// Output: [99, 2, 3] ← Shallow copy leaked change

System.out.println(Arrays.toString(deep.data));

// Output: [77, 2, 3] ← Deep copy is independent

}

}

skill-test-section-bg

82.9%

of professionals don't believe their degree can help them get ahead at work.

How to Copy an Object in Java – All Methods

How to copy an object in java: Java provides several mechanisms, each with different trade-offs in safety, effort, and performance. Understanding all approaches is essential for choosing the right one for a given situation.

Method

Mechanism

Copy Type

Effort

Best For

Copy Constructor

Define a constructor taking same-class object

Deep (manual)

High

Full control; recommended approach

Object.clone()

Implement Cloneable, call super.clone()

Shallow by default

Medium

Simple classes without mutable fields

Serialisation Trick

Serialise then deserialise

Deep (automatic)

Low code, high overhead

Quick deep copy without writing constructors

Manual Field Copy

Assign each field individually

Deep (manual)

High

One-off copies in specific methods

Copy Factory Method

Static factory returning a new copy

Deep (manual)

Medium

Preferred over clone() by Joshua Bloch

Method 1: Copy Constructor (Recommended)

Already covered in detail above – the recommended approach for

java copy object: full control, no interface required, works with all field types.

Method 2: Java Object Cloning via clone()

// java object cloning - implementing Cloneable

public class Employee implements Cloneable {

private String name;

private int salary;

private int[] bonuses; // Mutable - needs manual deep copy

public Employee(String name, int salary, int[] bonuses) {

this.name = name;

this.salary = salary;

this.bonuses = bonuses;

}

@Override

protected Employee clone() throws CloneNotSupportedException {

Employee cloned = (Employee) super.clone(); // Shallow clone

cloned.bonuses = this.bonuses.clone(); // Manual deep copy

return cloned;

}

public static void main(String[] args) throws CloneNotSupportedException {

Employee e1 = new Employee("Alice", 90000, new int[]{5000, 3000});

Employee e2 = e1.clone(); // java object cloning

e2.bonuses[0] = 0;

System.out.println(e1.bonuses[0]); // 5000 - unchanged (deep copy)

}

}

Method 3: Serialisation Deep Copy

// how to copy an object in java - serialisation trick

import java.io.*;

public class SerialCopy {

@SuppressWarnings("unchecked")

public static T deepCopy(T obj) {

try {

ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(bos);

oos.writeObject(obj);

ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());

ObjectInputStream ois = new ObjectInputStream(bis);

return (T) ois.readObject();

} catch (IOException | ClassNotFoundException e) {

throw new RuntimeException("Deep copy failed", e);

}

}

}

// Usage: Person copy = SerialCopy.deepCopy(original);

// Works automatically for all Serializable classes - no manual field copying

Method 4: Copy Factory Method (Joshua Bloch’s Recommendation)

// java copy object - copy factory method (preferred over clone())

public class Person {

private final String name;

private final int age;

private Person(String name, int age) {

this.name = name; this.age = age;

}

// Copy factory - static method returning a deep copy

public static Person copyOf(Person p) {

return new Person(p.name, p.age);

}

public static void main(String[] args) {

Person original = new Person("Java", 45);

Person copy = Person.copyOf(original);

System.out.println(copy == original); // false - independent objects

}

}

Copy Constructor in Java with Example Program – Extended

The following copy constructor in java with example program demonstrates a production-realistic scenario – a Student class with nested Address and an array of Grade objects, requiring a complete deep copy in java implementation.

// copy constructor in java program - full production example

import java.util.Arrays;

class Grade {

String subject;

int marks;

public Grade(String s, int m) { this.subject=s; this.marks=m; }

public Grade(Grade g) { this.subject=g.subject; this.marks=g.marks; }

}

class Address {

String city, country;

public Address(String c, String co) { this.city=c; this.country=co; }

public Address(Address a) { this.city=a.city; this.country=a.country; }

}

public class Student {

private String name;

private int age;

private Address address; // Nested mutable object

private Grade[] grades; // Array of mutable objects

// Parameterised constructor

public Student(String name, int age, Address address, Grade[] grades) {

this.name = name;

this.age = age;

this.address = address;

this.grades = grades;

}

// Deep copy constructor in java - handles all mutable fields

public Student(Student s) {

this.name = s.name; // String is immutable - safe

this.age = s.age; // Primitive - copied by value

this.address = new Address(s.address); // Deep copy nested object

this.grades = new Grade[s.grades.length]; // New array

for (int i = 0; i < s.grades.length; i++)

this.grades[i] = new Grade(s.grades[i]); // Deep copy each grade

}

public void display() {

System.out.println(name + " | Age: " + age +

" | City: " + address.city +

" | Grades: " + Arrays.toString(

Arrays.stream(grades).mapToInt(g->g.marks).toArray()));

}

public static void main(String[] args) {

Grade[] grades = { new Grade("Math",90), new Grade("Science",85) };

Address addr = new Address("Delhi", "India");

Student original = new Student("Mohan", 15, addr, grades);

Student copy = new Student(original); // Deep copy constructor

// Modify the copy - original must NOT change

copy.address.city = "Mumbai";

copy.grades[0].marks = 50;

System.out.print("Original: "); original.display();

System.out.print("Copy: "); copy.display();

}

}

// Output:

// Original: Mohan | Age: 15 | City: Delhi | Grades: [90, 85] ← Unchanged

// Copy: Mohan | Age: 15 | City: Mumbai | Grades: [50, 85]

Java Object Cloning - The clone() Method

Java object cloning via the clone() method is the alternative to the copy constructor. To use it, a class must implement the Cloneable interface and override clone() from Object. If Cloneable is not implemented, calling clone() throws CloneNotSupportedException.

Property

clone() Method

Interface required

Must implement Cloneable marker interface

Default behaviour

Shallow copy - super.clone() copies references

Deep copy

Requires manual override for each mutable field

Exception

Throws CloneNotSupportedException - must be handled

Return type

Returns Object - requires explicit casting

Inheritance

clone() is inherited from Object - available to all classes

Recommendation

Joshua Bloch (Effective Java) advises against it - use copy constructors or factories instead

Comparison: Copy Constructor vs clone() Method

Dimension

Copy Constructor

clone() Method

Definition

Special constructor taking same-class object

Method from Object - overridden with Cloneable

Interface required

None - no marker interface needed

Must implement Cloneable

Default copy type

Deep copy (manual - full control)

Shallow copy by default

Deep copy support

Full - explicit field-by-field control

Requires manual override per mutable field

Exception handling

No checked exceptions

Throws CloneNotSupportedException

Return type

New object of same type - no casting

Returns Object - requires explicit cast

Field access

Can access public, protected, and private fields

Can access public and protected only via super.clone()

Inheritance

Cannot be inherited - must define in each subclass

Inherited from Object - available universally

Performance

More efficient - direct member access

Slightly less efficient - method call + casting

Recommendation

Preferred - explicit, safe, flexible

Use with caution - error-prone for complex objects

Advantages & Disadvantages of Copy Constructor in Java

Advantage

Disadvantage

Full control over copying - including deep copy in java

Must be manually implemented in each class and subclass

No interface required - unlike Cloneable

Cannot be inherited - must be re-defined per subclass

Accesses all fields (public, protected, private)

Does not support serialisation directly

Safe object initialisation - prevents shared mutable state

More code than assignment (p1 = p2) for simple objects

Flexible - customise copy behaviour per class

Risk of implementation errors (forgetting to copy a field)

Applications of Copy Constructor in Java

Deep Copy of Complex Objects: When an object contains mutable nested objects (lists, arrays, other objects), the copy constructor ensures the duplicate is fully independent - preventing unintended shared state.

Immutable Object Design: Copy constructors are used to create defensive copies of mutable parameters passed into constructors, ensuring the immutable object's internal state cannot be modified externally.

Object Caching & Prototyping: The Prototype design pattern uses copy constructors to clone pre-configured objects - creating new instances from a cached prototype rather than initialising from scratch.

Undo/Redo Systems: Applications like text editors snapshot object state using copy constructors - each edit creates a deep copy of the current state to enable undo.

Thread Safety: Creating deep copies of shared mutable objects before passing them to different threads prevents race conditions and data corruption.

Builder Pattern: Copy constructors are used to create a working copy of an object before applying incremental modifications through a builder, then discarding the copy if any step fails.

Conclusion

The copy constructor in java is the most controlled, flexible, and recommended way to java copy object - especially when deep copying is required. Understanding shallow copy vs deep copy in java is critical: always use deep copy when your class contains mutable reference fields (arrays, collections, nested objects) to ensure the copy is fully independent.

The copy constructor in java with example program in this guide demonstrates both patterns - from the basic Student example to the production-realistic multi-level deep copy. Compared to java object cloning via clone(), the copy constructor is safer, more explicit, and more maintainable.

To master Java OOP patterns and build production-grade applications, explore the Certificate Program in Application Development powered by Hero Vired.

People Also Ask

What is a copy constructor in Java?

Copy constructor in java: a special constructor that takes an object of the same class as its argument and creates a new independent object with the same field values. Java does not provide one automatically - it must be explicitly defined. The copy constructor provides full control over which fields are copied and how nested mutable objects are handled.

What is the difference between shallow copy and deep copy in Java?

Shallow copy vs deep copy in java: shallow copy duplicates field values but copies reference-type fields by reference - original and copy share the same nested objects. Deep copy creates new independent instances of all mutable fields. The copy constructor in java program produces a deep copy when it explicitly creates new objects for each mutable reference field (arrays, nested classes).

How do you copy an object in Java?

How to copy an object in java: four main approaches - (1) Copy Constructor: define a constructor that takes the same class as parameter and manually copies fields; (2) java object cloning: implement Cloneable and override clone(); (3) Serialisation: serialise then deserialise - automatic deep copy for Serializable classes; (4) Copy Factory Method: static method returning a new copy. Copy constructor is the recommended approach.

Is a copy constructor better than clone() in Java?

Yes, for most cases. The copy constructor in java is generally preferred over clone() because: it requires no Cloneable interface, it throws no checked exceptions, it can access private fields directly, it provides explicit control over deep copy in java, and it avoids the confusing type-casting requirement of clone(). Joshua Bloch recommends copy constructors or copy factories over clone() in Effective Java.

What are the types of Java constructors?

The four main java constructor types: Default Constructor (no-arg, Java-provided if none defined), Parameterised Constructor (accepts arguments to set initial state), Copy Constructor (takes same-class object, creates independent duplicate - the focus of this article), and Private Constructor (prevents external instantiation - used in Singleton pattern). The java copy constructor example shows the copy constructor type in action.

FAQs
Define the copy constructor in OOPS.
In OOPS, a copy constructor is a special constructor that creates a new object by copying its existing state. It provides the most fitting way to initialize objects through duplication.
What is the use of a Copy Constructor?
The Copy Constructor is used when objects need to be duplicated while maintaining their state integrity or when objects are initialized based on existing instances.
Is it possible to create a deep copy using a copy constructor?
No. By default, a copy constructor only creates a shallow copy. In order to create a deep copy, we need to handle deep copying logic within the copy constructor.
What is the main difference between a regular constructor and a copy constructor?
A regular constructor is used to initialize a new object, whereas a copy constructor creates an object by copying its existing state.

Updated on April 16, 2026

Link
Loading related articles...