A Copy Constructor in Java is a special type of Constructor, which enables us to get a copy of an existing object. Copy Constructors can take only one parameter, which is a reference of the same class.
In this article lets understand what is copy constructor and its uses.
The Copy Constructor helps us overcome the design issues of the clone() method. Copy Constructor comes in handy when you want to copy an object which has a lot of attributes.
Before getting into the details of Copy Constructor in Java, let’s understand the advantages of Copy Constructor over Object.clone() method
Advantages of copy constructors over Object.clone()
- Unlike clone() method, Copy Constructors will not force us to implement the Cloneable or Serializable interface
- Copy Constructor in Java is much easier to use even when the object has complex attributes.
- It gives us the complete control over object copy, we can even mix both Deep Copy and Shallow Copy for different attributes of the class.
- clone() method throws CloneNotSupportedException whenever the class does not implement Cloneable interface, Copy Constructor will not be throwing these Exceptions.
- Typecasting is required as the clone() method returns Object type, whereas Copy Constructor does not need such typecasting.
- Copy Constructor will let us change the value of a final attribute whereas clone() method will throw compilation error when you try to change a final field.
Copy Constructor in Java
- In the below code the Person class has two variables x and y, a constructor with two arguments and a copy constructor.
- We have created a Person object p1 by passing the values to its constructor and Person object p2 by passing the p1 to the Copy Constructor.
- Once when we try to print the value of both the object p1 and p2 we will get same result 1 & 2.
- Now we have changed the value of p2.x -> 3 and p2.y ->4, since primitives are by default deep copied we can change the values.
- When we print again we will get the value of 1 & 2 for p1 and 3 & 4 for p2.
package com.javainterviewpoint; public class Person { public int x; public int y; //Constructor with 2 parameters public Person(int x, int y) { super(); this.x = x; this.y = y; } //Copy Constructor public Person(Person p) { this.x = p.x; this.y = p.y; } public static void main(String[] args) { Person p1 = new Person(1,2); Person p2 = new Person(p1); System.out.println(p1.x + " " + p1.y); // prints "1 2" System.out.println(p2.x + " " + p2.y); // prints "1 2" p2.x = 3; p2.y = 4; System.out.println(p1.x + " " + p1.y); // prints "1 2" System.out.println(p2.x + " " + p2.y); // prints "3 4" } }
Java Deep Copy of references
With Copy Constructors we can achieve both Shallow Copy and Deep Copy
If a class has any references to other objects as fields, then only references of those objects are copied into clone object, a fresh copy of those objects are not created.
We need to use the new operator inside the Copy Constructor for it to be deep copied.
Let’s understand importance of a new keyword in below scenario with an example
Shallow Copying
Person.java
package com.javainterviewpoint; public class Person { public int x; public int y; public Address address; //Constructor with 2 parameters public Person(int x, int y, Address address) { super(); this.x = x; this.y = y; this.address = address; } //Copy Constructor public Person(Person p) { this.x = p.x; this.y = p.y; this.address = p.address; //Shallow Copying } public static void main(String[] args) { Address address = new Address("Chennai","TN"); Person p1 = new Person(1,2,address); Person p2 = new Person(p1); System.out.println("*** Before changes ***"); System.out.println(p1.address.city+" "+p1.address.state); System.out.println(p2.address.city+" "+p2.address.state); //Lets change the city and state of P2 object p2.address.city = "Banglore"; p2.address.state = "Karnataka"; System.out.println("*** After change ***"); System.out.println(p1.address.city+" "+p1.address.state); System.out.println(p2.address.city+" "+p2.address.state); } }
Address.java
package com.javainterviewpoint; public class Address { public String city; public String state; public Address(String city, String state) { super(); this.city = city; this.state = state; } public Address(Address address) { this.city = address.city;; this.state = address.state; } }
Output
*** Before changes *** Chennai TN Chennai TN *** After change *** Banglore Karnataka Banglore Karnataka
- The Person class we have two variable x , y and instance of Address class. We have created two objects p1 and p2 (through copy constructor)
- We have changed the city and state of the cloned object p2, but it gets reflected in the original object p1 object also.
- This is because shallow copying, the Address member of the both original object p1, cloned object p2 refers to the same memory location.
Deep Copying
Lets now change our implementation from shallow Copying to deep Copying.
package com.javainterviewpoint; public class Person { public int x; public int y; public Address address; //Constructor with 2 parameters public Person(int x, int y, Address address) { super(); this.x = x; this.y = y; this.address = address; } //Copy Constructor public Person(Person p) { this.x = p.x; this.y = p.y; this.address = new Address(p.address); //Deep Copying } public static void main(String[] args) { Address address = new Address("Chennai","TN"); Person p1 = new Person(1,2,address); Person p2 = new Person(p1); System.out.println("*** Before changes ***"); System.out.println(p1.address.city+" "+p1.address.state); System.out.println(p2.address.city+" "+p2.address.state); //Lets change the city and state of P2 object p2.address.city = "Banglore"; p2.address.state = "Karnataka"; System.out.println("*** After change ***"); System.out.println(p1.address.city+" "+p1.address.state); System.out.println(p2.address.city+" "+p2.address.state); } }
We have used the new keyword to implement deep copying, now if we see the output of p1 and p2 object is different.
Output
*** Before changes *** Chennai TN Chennai TN *** After change *** Chennai TN Banglore Karnataka
Leave a Reply