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.
NICE
Thanks 🙂
Nice ❤
good one Thanks dear 🙂
thanks
Great,very helpful
Thank you so much 🙂
very good explanation, i have a small doubt. Thank for advance.
For deep cloning which one is better,serialization or copy constructor ???????
I prefer to deep cloning.
You can refer also refer How to write a Copy Constructor in java using Deep copy.
Thank u so much..it is really understandable…
Reblogged this on One Ordinary Blog.
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.
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.
Real informative and excellent anatomical structure of content material, now that’s user pleasant (:.