Java Copy Constructor

1. Introduction

A copy constructor in a Java class is a constructor that creates an object using another object of the same Java class.

That’s helpful when we want to copy a complex object that has several fields, or when we want to make a deep copy of an existing object.

2. How to Create a Copy Constructor

To create a copy constructor, we can first declare a constructor that takes an object of the same type as a parameter:

public class Employee {
    private int id;
    private String name;
  
    public Employee(Employee employee) {
    }
}

Then, we copy each field of the input object into the new instance:

public class Employee {
    private int id;
    private String name;
    
    public Employee(Employee employee) {
        this.id = employee.id;
        this.name = employee.name;
    }
}

What we have here is a shallow copy, which is fine since all of our fields – an int and a String in this case – are either primitive types or immutable types.

If the Java class has mutable fields, then we can instead make a deep copy inside its copy constructor. With a deep copy, the newly created object is independent of the original one because we create a distinct copy of each mutable object:

public class Employee {
    private int id;
    private String name;
    private Date startDate;

    public Employee(Employee employee) {
        this.id = employee.id;
        this.name = employee.name;
        this.startDate = new Date(employee.startDate.getTime());
    }
}

3. Copy Constructor vs. Clone

In Java, we can also use the clone method to create an object from an existing object. However, the copy constructor has some advantages over the clone method:

  1. The copy constructor is much easier to implement. We do not need to implement the Cloneable interface and handle CloneNotSupportedException.
  2. The clone method returns a general Object reference. Therefore, we need to typecast it to the appropriate type.
  3. We can not assign a value to a final field in the clone method. However, we can do so in the copy constructor.

4. Inheritance Issues

Copy constructors in Java are not inheritable by subclasses. Therefore, if we try to initialize a child object from a parent class reference, we will face a casting issue when cloning it with the copy constructor.

To illustrate this issue, let’s first create a subclass of Employee and its copy constructor:

public class Manager extends Employee {
    private List<Employee> directReports;
    // ... other constructors

    public Manager(Manager manager) {
        super(manager.id, manager.name, manager.startDate);
        this.directReports = directReports.stream()
          .collect(Collectors.toList());
    }
}

Then, we declare an Employee variable and instantiate it with the Manager constructor:

Employee source = new Manager(1, "VietManager", startDate, directReports);

Since the reference type is Employee, we have to cast it to Manager type so that we can use the copy constructor of the Manager class:

Employee clone = new Manager((Manager) source);

We may get ClassCastException at runtime if the input object is not an instance of Manager class.

One way to avoid casting in the copy constructor is to create a new inheritable method for both classes:

public class Employee {
   public Employee copy() {
        return new Employee(this);
    }
}

public class Manager extends Employee {
    @Override
    public Employee copy() {
        return new Manager(this);
    }
}

In each class method, we call its copy constructor with the input of this object. In this way, we can guarantee that the generated object equals the caller object:

Employee clone = source.copy();

5. Conclusion

In this tutorial, we showed how to create a copy constructor with some code examples. Also, we discussed several reasons why we should avoid the clone method.

Copy constructor has a casting issue when we use it to clone a child class object whose reference type is the parent class. We provided one solution for this issue.

As always, the source code for the tutorial is available over on GitHub.

Related posts:

Format ZonedDateTime to String
Java Program to Implement CopyOnWriteArraySet API
Java Program to Find the Number of Ways to Write a Number as the Sum of Numbers Smaller than Itself
Reversing a Linked List in Java
Quick Guide to Spring Controllers
Java Byte Array to InputStream
Java Program to Generate Date Between Given Range
Hướng dẫn Java Design Pattern – DAO
Spring Cloud Bus
Java Program to Implement Quick sort
Java Program to Implement Queue using Two Stacks
Java – Create a File
Spring Boot - Introduction
Java Program to Represent Graph Using Adjacency Matrix
Creating Docker Images with Spring Boot
Java Program to Perform Quick Sort on Large Number of Elements
Prevent Brute Force Authentication Attempts with Spring Security
A Quick Guide to Using Keycloak with Spring Boot
CharSequence vs. String in Java
Java Program to Check Whether Topological Sorting can be Performed in a Graph
Java Program to Check whether Directed Graph is Connected using DFS
Java Web Services – Jersey JAX-RS – REST và sử dụng REST API testing tools với Postman
Map Serialization and Deserialization with Jackson
Spring Data – CrudRepository save() Method
Java Program to Check if a Point d lies Inside or Outside a Circle Defined by Points a, b, c in a Pl...
The StackOverflowError in Java
Convert Character Array to String in Java
Java Program to Implement Triply Linked List
Java Program to Check if a Given Graph Contain Hamiltonian Cycle or Not
Java Program to Perform String Matching Using String Library
Spring Boot - Actuator
Java Program to Generate Random Numbers Using Probability Distribution Function