Advanced Java September 28 ,2025

Cloning in java

The Prototype Design Pattern is a creational design pattern that allows us to create new objects by cloning existing ones instead of building them from scratch. This is particularly useful when object creation is costly, time-consuming, or complex.

In Java, cloning is usually implemented with the Cloneable interface and the clone() method. But there’s a catch: you can either perform Shallow Cloning or Deep Cloning. The difference between them is subtle but extremely important.

This blog will guide you step by step through theory, practical implementations, comparisons, pitfalls, best practices, and real-world use cases of shallow and deep cloning in the Prototype Design Pattern.

Why Cloning?

Consider situations like:

  • A game engine cloning multiple enemies with the same attributes.
  • A document editor duplicating shapes or templates.
  • A large enterprise application caching objects instead of rebuilding them.

In all these cases, it is inefficient to create new objects from scratch. Instead, you clone an existing prototype.

Shallow Cloning

Definition

Shallow cloning creates a new object, but nested objects are not copied. Instead, their references are shared.

  • Primitive fields → copied directly.
  • Object references → shared (point to the same object).

Example

class Address {
    String city;
    String state;

    public Address(String city, String state) {
        this.city = city;
        this.state = state;
    }
}

class Employee implements Cloneable {
    int id;
    String name;
    Address address;

    public Employee(int id, String name, Address address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone(); // Shallow copy
    }
}

public class ShallowCloneDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address addr = new Address("Delhi", "Delhi");
        Employee emp1 = new Employee(101, "Saumya", addr);

        Employee emp2 = (Employee) emp1.clone();

        System.out.println("Before modification:");
        System.out.println("emp1 city: " + emp1.address.city);
        System.out.println("emp2 city: " + emp2.address.city);

        emp2.address.city = "Mumbai"; // Modify clone’s nested object

        System.out.println("\nAfter modification:");
        System.out.println("emp1 city: " + emp1.address.city);
        System.out.println("emp2 city: " + emp2.address.city);
    }
}

Output

Before modification:
emp1 city: Delhi
emp2 city: Delhi

After modification:
emp1 city: Mumbai
emp2 city: Mumbai

👉 Drawback: Both objects point to the same Address. Changing one affects the other.

Deep Cloning

Definition

Deep cloning creates a completely independent copy of an object, including all nested objects.

  • Primitive fields → copied directly.
  • Nested objects → cloned recursively.

Example

class Address implements Cloneable {
    String city;
    String state;

    public Address(String city, String state) {
        this.city = city;
        this.state = state;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone(); // Creates a new Address object
    }
}

class Employee implements Cloneable {
    int id;
    String name;
    Address address;

    public Employee(int id, String name, Address address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Employee cloned = (Employee) super.clone();
        cloned.address = (Address) address.clone(); // Deep copy
        return cloned;
    }
}

public class DeepCloneDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Employee emp1 = new Employee(101, "Saumya", new Address("Delhi", "Delhi"));
        Employee emp2 = (Employee) emp1.clone();

        System.out.println("Before modification:");
        System.out.println("emp1 city: " + emp1.address.city);
        System.out.println("emp2 city: " + emp2.address.city);

        emp2.address.city = "Mumbai"; // Modify clone’s nested object

        System.out.println("\nAfter modification:");
        System.out.println("emp1 city: " + emp1.address.city);
        System.out.println("emp2 city: " + emp2.address.city);
    }
}

Output

Before modification:
emp1 city: Delhi
emp2 city: Delhi

After modification:
emp1 city: Delhi
emp2 city: Mumbai

👉 Success: Now emp1 and emp2 are independent.

Other Approaches to Deep Cloning

Apart from Cloneable, there are alternative techniques:

1. Copy Constructors

class Employee {
    int id;
    String name;
    Address address;

    public Employee(Employee other) {
        this.id = other.id;
        this.name = other.name;
        this.address = new Address(other.address.city, other.address.state);
    }
}

✔️ Easy to read, safe, explicit.

2. Serialization-based Cloning

import java.io.*;

class SerializationUtils {
    @SuppressWarnings("unchecked")
    public static  T clone(T object) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);
            out.writeObject(object);

            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream in = new ObjectInputStream(bis);
            return (T) in.readObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

✔️ Works well when all classes are Serializable.
❌ Slower compared to clone().

3. Apache Commons Lang

import org.apache.commons.lang3.SerializationUtils;

Employee emp2 = SerializationUtils.clone(emp1);

✔️ Convenient for enterprise use.
✔️ Requires dependency (commons-lang3).

Shallow vs Deep Cloning – Side-by-Side

FeatureShallow CloningDeep Cloning
Primitive fieldsCopied directlyCopied directly
Nested objectsReferences sharedDuplicated recursively
IndependenceNot independentFully independent
PerformanceFaster, lightweightSlower, more resource-heavy
Memory usageLessMore
Use caseSimple/immutable objectsComplex/mutable/nested objects

Pitfalls to Avoid

  1. Forgetting to deep clone nested objects → causes shared state issues.
  2. Cyclic references → can cause infinite recursion in deep cloning.
  3. Misusing Cloneable → Java’s clone() is tricky and not enforced strictly.
  4. Over-cloning → unnecessary deep copies can hurt performance.
  5. Serialization overhead → may slow down large-scale systems.

Best Practices

  • Use shallow cloning for immutable/simple objects.
  • Use deep cloning for mutable and complex objects.
  • Prefer copy constructors for clarity and maintainability.
  • Use libraries (Apache Commons, ModelMapper) in large applications.
  • Always document whether your clone is shallow or deep.

Real-World Applications of Prototype Pattern

  1. Game Development → clone enemies or characters.
  2. Graphics & Document Editors → duplicate shapes, templates, or slides.
  3. Machine Learning → duplicate model configurations.
  4. Caching → serve clients with object copies.
  5. UI Frameworks → clone reusable components.

Final Thoughts

The Prototype Design Pattern is a powerful way to reduce object creation costs. But its effectiveness depends on how cloning is handled:

  • Shallow Cloning: Fast, simple, but risky with mutable objects.
  • Deep Cloning: Safe and independent, but slower and more resource-intensive.

In practice:

  • Use shallow cloning for small or immutable objects.
  • Use deep cloning for nested or mutable structures.
  • For enterprise systems, consider copy constructors or serialization-based approaches for safety and flexibility.

The right choice depends on your performance requirements, object complexity, and system design.

 

Sanjiv
0

You must logged in to post comments.

Related Blogs

Generics P...
Advanced Java August 08 ,2025

Generics Part- 2

Collection...
Advanced Java July 07 ,2025

Collections Framewor...

Mastering...
Advanced Java August 08 ,2025

Mastering Java Multi...

Annotation...
Advanced Java August 08 ,2025

Annotations

Java Memor...
Advanced Java August 08 ,2025

Java Memory Manageme...

Java Lambd...
Advanced Java August 08 ,2025

Java Lambda Expressi...

Java Funct...
Advanced Java August 08 ,2025

Java Functional Inte...

Java Strea...
Advanced Java August 08 ,2025

Java Stream API

JDBC (Java...
Advanced Java August 08 ,2025

JDBC (Java Database...

JDBC (Java...
Advanced Java September 09 ,2025

JDBC (Java Database...

Annotation...
Advanced Java August 08 ,2025

Annotations

Generics
Advanced Java August 08 ,2025

Generics

Java I/O (...
Advanced Java August 08 ,2025

Java I/O (NIO)

Introducti...
Advanced Java September 09 ,2025

Introduction to Desi...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Other Prin...
Advanced Java September 09 ,2025

Other Principles Beh...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Builder De...
Advanced Java September 09 ,2025

Builder Design Patte...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Chain of R...
Advanced Java September 09 ,2025

Chain of Responsibil...

Command De...
Advanced Java September 09 ,2025

Command Design Patte...

Interprete...
Advanced Java September 09 ,2025

Interpreter Design P...

Iterator D...
Advanced Java September 09 ,2025

Iterator Design Patt...

Mediator D...
Advanced Java September 09 ,2025

Mediator Design Patt...

Memento De...
Advanced Java September 09 ,2025

Memento Design Patte...

Observer D...
Advanced Java September 09 ,2025

Observer Design Patt...

State Desi...
Advanced Java September 09 ,2025

State Design Pattern...

Strategy D...
Advanced Java September 09 ,2025

Strategy Design Patt...

Template M...
Advanced Java September 09 ,2025

Template Method Desi...

Visitor De...
Advanced Java September 09 ,2025

Visitor Design Patte...

Java 8+ Fe...
Advanced Java October 10 ,2025

Java 8+ Features

SOLID Prin...
Advanced Java October 10 ,2025

SOLID Principles in...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

How Iterat...
Advanced Java October 10 ,2025

How Iterators Work i...

How Concur...
Advanced Java October 10 ,2025

How ConcurrentHashMa...

Comparable...
Advanced Java October 10 ,2025

Comparable vs Compar...

Get In Touch

G06, Kristal Olivine Bellandur near Bangalore Central Mall, Bangalore Karnataka, 560103

+91-8076082435

techiefreak87@gmail.com