Dictionary meaning of cloning.
Cloning: make an identical copy of.
Object cloning: refers to creation of exact copy of an object. Object class clone() method is used to clone an object in java.
Clone() method: Creates and returns a copy of this object.
protected Object clone() throws CloneNotSupportedException
Note: The class whose object have to be cloned must implement the java.lang.Cloneable interface otherwise clone() method will throw CloneNotSupportedException.
Why use clone() method?
The clone() methods copies the values of an object to another. The clone() method saves the extra processing task for creating the exact copy of an object.
Main disadvantage of clone() method: It does not invoke any constructor so we don’t have any control over object construction.
Types of cloning in java
- Shallow Cloning
- Deep Cloning
Shallow Cloning
Shallow means having little depth.
Shallow copy of an object create a new object and copies all the field of object to the new object (either it is primitive or a reference). In case of non-primitive types only reference will be copied to the new instance. Therefore both original object and new object will point to the same non-primitive type fields i.e. objects. It returns an instance of Object class we have to explicitly cast to the original object.
Let’s consider the below example, we have a Customer class which have two properties name and address. In case of shallow copy a new Customer object will be created and as both name, address fields are of non-primitive type there references will be copied to new object. Now both the original object and copied object will point to the same name and address objects.
Here what is important that in case of name values will not reflect in other if we change it in one object. This is because of immutable nature of string objects.
Shallow cloning example
package com.w3schools; class Address implements Cloneable{ private String city; private String pinCode; public Address(String city, String pinCode) { this.city = city; this.pinCode = pinCode; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getPinCode() { return pinCode; } public void setPinCode(String pinCode) { this.pinCode = pinCode; } public Object clone()throws CloneNotSupportedException{ return super.clone(); } } class Customer implements Cloneable { private String name; private Address address; public Customer(String name, Address address) { this.name = name; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Object clone()throws CloneNotSupportedException{ return super.clone(); } } public class Test { public static void main(String args[]){ try{ Customer originalObj = new Customer("Vivek", new Address("Gurgaon", "122001")); Customer clonedObj=(Customer)originalObj.clone(); System.out.println("Original Object properties: "); System.out.println(originalObj.getName()); System.out.println(originalObj.getAddress().getCity()); System.out.println(originalObj.getAddress().getPinCode()); System.out.println("Cloned Object properties: "); System.out.println(clonedObj.getName()); System.out.println(clonedObj.getAddress().getCity()); System.out.println(clonedObj.getAddress().getPinCode()); //Change in cloned object clonedObj.getAddress().setPinCode("122002"); //Changes will reflect in original object also System.out.println("Original Object pincode after changes in cloned object: "); System.out.println(originalObj.getAddress().getPinCode()); }catch(CloneNotSupportedException c){ } } }
Output
Original Object properties: Vivek Gurgaon 122001 Cloned Object properties: Vivek Gurgaon 122001 Original Object pincode after changes in cloned object: 122002
Deep Clonnging
Deep copy of an object create a fully independent copy of an object. In case of deep copy everything will be copied to the new object. After deep copy, original object and copied object will refers to the different primitive and non-primitive fields. Changes on one object’s fields will not reflects in other’s.
Let’s consider the same example which we discussed earlier. We have a Customer class which have two properties name and address. In case of deep copy a new independent Customer object will be created. Now the original object and copied object will point to the different name and address objects.
Here what is important that in case of name values will not reflect in other if we change it in one object. This is because of immutable nature of string objects. So we do not have to do explicit cloning for that.
Deep cloning example
package com.w3schools; class Address implements Cloneable{ private String city; private String pinCode; public Address(String city, String pinCode) { this.city = city; this.pinCode = pinCode; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getPinCode() { return pinCode; } public void setPinCode(String pinCode) { this.pinCode = pinCode; } public Object clone()throws CloneNotSupportedException{ return super.clone(); } } class Customer implements Cloneable { private String name; private Address address; public Customer(String name, Address address) { this.name = name; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Object clone()throws CloneNotSupportedException{ Customer customer = (Customer) super.clone(); customer.address = (Address)this.address.clone(); return customer; } } public class Test { public static void main(String args[]){ try{ Customer originalObj = new Customer("Vivek", new Address("Gurgaon", "122001")); Customer clonedObj=(Customer)originalObj.clone(); System.out.println("Original Object properties: "); System.out.println(originalObj.getName()); System.out.println(originalObj.getAddress().getCity()); System.out.println(originalObj.getAddress().getPinCode()); System.out.println("Cloned Object properties: "); System.out.println(clonedObj.getName()); System.out.println(clonedObj.getAddress().getCity()); System.out.println(clonedObj.getAddress().getPinCode()); //Change in cloned object clonedObj.getAddress().setPinCode("122002"); //Changes will not reflect in original object also System.out.println("Original Object pincode after changes in cloned object: "); System.out.println(originalObj.getAddress().getPinCode()); }catch(CloneNotSupportedException c){ } } }
Output
Original Object properties: Vivek Gurgaon 122001 Cloned Object properties: Vivek Gurgaon 122001 Original Object pincode after changes in cloned object: 122001
Note:
- clone() method of the object class support shallow copy of the object.
- In case of deep copy we have to override the clone() method of the object class and we also need to ensure that all the member class also implement the Cloneable interface.
- There is no difference between shallow and deep copy in java if only primitive type fields or Immutable objects are there as fields in the original object.