Copy Constructors in Java

Hi all,

We have a new topic over here to learn – The Copy Constructors.

WHAT ?

A copy constructor is a constructor that takes only one argument which is of the type as the class in which the copy constructor is implemented. For example, let us assume a class namely Car and it has a constructor called copy constructor which expects only one argument of type Car.

WHY ?

Copy constructors are widely used for creating a duplicates of objects known as cloned objects. Duplicate object in the sense the object will have the same characteristics of the original object from which duplicate object is created. But we have to ensure that both original and duplicate objects refer to different memory locations.

WHERE ?

It’s our responsibility to implement a copy constructor in our class in the right way. As mentioned above, it’s used to duplicate objects. So we are free to use copy constructors instead of clone method in java.

HOW ?

Copy constructors are implemented for deep cloning and shallow cloning. Both these cloning techniques can be achieved by overriding the clone method in java. Shallow cloning is the default cloning implementation in java and we just need to override the clone method. But deep cloning has to be implemented as per our need and logic. Explaining about cloning is beyond the scope of this post. So let’s come back.

When you pass an instance of a particular class to copy constructor, it returns a new instance of the same class with all values copied from the parameter instance. Let’s see to an example.

Department.java


public class Department {

    private String name;
    private int id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Department(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Department(Department oldDepartment) {
        this.id = oldDepartment.id;
        this.name = oldDepartment.name;
    }

    @Override
    public String toString() {
        return "Department Id: " + id + "\tDepartment Name: " + name;
    }
}

Employee.java


public class Employee {

    private String name;
    private int id;
    private Department department;

    public Department getDepartment() {
        return department;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Employee(int id, String name, Department department) {
        this.id = id;
        this.name = name;
        this.department = department;
    }

    public Employee(Employee oldEmployee) {
        this.id = oldEmployee.id;
        this.name = oldEmployee.name;
        this.department = oldEmployee.department;  //shallow cloning
    }

    @Override
    public String toString() {
        return "Employee Id: " + id + "\tEmployee Name: " + name + "\t" + department;
    }
}

Okay, it’s the time to test. Let’s do that.

CopyConstructors.java


public class CopyConstructorTest {

   public static void main(String[] args) {
        Department department = new Department(1, "Finance");
        Employee originalEmployee = new Employee(1, "Ram", department);
        Employee clonedEmployee = new Employee(originalEmployee);
        System.out.println("Original:- " + originalEmployee);
        System.out.println("Duplicate:- " + clonedEmployee);
        System.out.println();
        clonedEmployee.setId(2);
        clonedEmployee.setName("Laxman");
        clonedEmployee.getDepartment().setName("HR");
        System.out.println("Original:- " + originalEmployee);
        System.out.println("Duplicate:- " + clonedEmployee);
    }
}

The Output

Original:- Employee Id: 1	Employee Name: Ram	Department Id: 1	Department Name: Finance
Duplicate:- Employee Id: 1	Employee Name: Ram	Department Id: 1	Department Name: Finance

Original:- Employee Id: 1	Employee Name: Ram	Department Id: 1	Department Name: HR
Duplicate:- Employee Id: 2	Employee Name: Laxman	Department Id: 1	Department Name: HR

What have we done above? We have two classes namely Department and Employee and created their copy constructors in the respective classes. The Department class has only two variables namely id and name. In the Employee class, there are two variables and an instance of Department class.

Then we create an object of Employee class namely originalEmployee in the main method and create a duplicate object namely clonedEmployee of the originalEmployee object.

But what happens in the above example is, when we change the department name of clonedEmployee, the change comes up with the originalEmployee also (just look over the output, the department name of originalEmployee object changed from Finance to HR). Why it behaves so because what we implement here is shallow cloning (see the highlighted line). It means the department member of both originalEmployee and clonedEmployee refers to the same memory location. When our implementation is changed from shallow cloning to deep cloning, the following things happen.

Let’s have a small change in the copy constructor of Employee class (look over the following highlighted line).

Employee.java


public class Employee {

    private String name;
    private int id;
    private Department department;

    public Department getDepartment() {
        return department;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Employee(int id, String name, Department department) {
        this.id = id;
        this.name = name;
        this.department = department;
    }

    public Employee(Employee oldEmployee) {
        this.id = oldEmployee.id;
        this.name = oldEmployee.name;
        this.department = new Department(oldEmployee.department);    //deep cloning
    }

    @Override
    public String toString() {
        return "Employee Id: " + id + "\tEmployee Name: " + name + "\t" + department;
    }
}

Now we test again and the output is

Original:-  Employee Id: 1	Employee Name: Ram	Department Id: 1	Department Name: Finance
Duplicate:- Employee Id: 1	Employee Name: Ram	Department Id: 1	Department Name: Finance

Original:-  Employee Id: 1	Employee Name: Ram	Department Id: 1	Department Name: Finance
Duplicate:- Employee Id: 2	Employee Name: Laxman	Department Id: 1	Department Name: HR

Now everything goes fine and this is what we call deep cloning using copy constructors.

SUBSTITUTE ?

In certain situations we can’t make our copy constructor public, so it has to be private. Now we need to think about an equivalent and yes, fortunately we are able to find out another workaround for achieving the same result- The Factory Method. Let’s have a look.

Employee.java


public class Employee {

    private String name;
    private int id;
    private Department department;

    public Department getDepartment() {
        return department;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Employee(int id, String name, Department department) {
        this.id = id;
        this.name = name;
        this.department = department;
    }

    private Employee(Employee oldEmployee) {
        this.id = oldEmployee.id;
        this.name = oldEmployee.name;
        this.department = new Department(oldEmployee.department);    //deep cloning
    }

    @Override
    public String toString() {
        return "Employee Id: " + id + "\tEmployee Name: " + name + "\t" + department;
    }

    public static Employee copy(Employee originalEmployee) {
        return new Employee(originalEmployee);
    }
}

Now we can make our copy constructor private (making it so is a good achievement) and our factory method in turn calls the constructor. It also gives us the same output. Let’s test it right away.

CopyConstructorTest.java


public class CopyConstructorTest {

    public static void main(String[] args) {
        Department department = new Department(1, "Finance");
        Employee originalEmployee = new Employee(1, "Ram", department);
        Employee clonedEmployee = Employee.copy(originalEmployee);
        System.out.println("Original:- " + originalEmployee);
        System.out.println("Duplicate:- " + clonedEmployee);
        System.out.println();
        clonedEmployee.setId(2);
        clonedEmployee.setName("Laxman");
        clonedEmployee.getDepartment().setName("HR");
        System.out.println("Original:- " + originalEmployee);
        System.out.println("Duplicate:- " + clonedEmployee);
    }
}

The Output


Original:- Employee Id: 1	Employee Name: Ram	Department Id: 1	Department Name: Finance
Duplicate:- Employee Id: 1	Employee Name: Ram	Department Id: 1	Department Name: Finance

Original:- Employee Id: 1	Employee Name: Ram	Department Id: 1	Department Name: Finance
Duplicate:- Employee Id: 2	Employee Name: Laxman	Department Id: 1	Department Name: HR

Thanks.

Published by

Deepesh Darshan K R

I am Me. In all the world, there is no one else exactly like me. Everything that comes out of me is authentically mine, because I alone chose it. I own everything about me: my body, my feelings, my mouth, my voice, all my actions, whether they be to others or myself. I own my fantasies, my dreams, my hopes, my fears. I own my triumphs and successes, all my failures and mistakes. Because I own all of me, I can become intimately acquainted with me. By so doing, I can love me and be friendly with all my parts. I know there are aspects about myself that puzzle me, and other aspects that I do not know -- but as long as I am friendly and loving to myself, I can courageously and hopefully look for solutions to the puzzles and ways to find out more about me. However I look and sound, whatever I say and do, and whatever I think and feel at a given moment in time is authentically me. If later some parts of how I looked, sounded, thought, and felt turn out to be unfitting, I can discard that which is unfitting, keep the rest, and invent something new for that which I discarded. I can see, hear, feel, think, say, and do. I have the tools to survive, to be close to others, to be productive, and to make sense and order out of the world of people and things outside of me. I own me, and therefore, I can engineer me. I am me, and . . . . . . . . . . I am Okay. Haha.. Let it go.. I am a software engineer working in a MNC here at Kochi itself, specialized on J2EE platform, dribbling with frameworks like struts, hibernate etc.

18 thoughts on “Copy Constructors in Java”

  1. very good explanation, i have a small doubt. Thank for advance.
    For deep cloning which one is better,serialization or copy constructor ???????

  2. Thanks for the wonderful explanation.
    I have couple of questions though on copy constructors:-
    1. I believed that constructors has to be always public so a copy constructor should also follow the same rule which is not the case here can you explain why.
    2. why is factory method Static.

  3. Awesome, very well written article. Many important points are covered here.Its really a great and useful piece of information. Im glad that you shared this helpful information with us.
    Please stay us up to date like this. Thanks for sharing.

Leave a comment