How to deep clone an object in Java
deep
clone
Java
In this article will present how to deep clone an object. This is required when the variables from the object are other objects or lists. What actually happens if the deep cloning technique is not applied? The child object that is not cloned will actually be the same in both parent objects.
To see how to clone a simple (shallow) object check How to clone an object in Java tutorial.
Example
In order to see how deep clone needs to be implemented will create 2 classes: User and Address. The User class will have an Adress object. Both classes need to implements Cloneable Interface.
User.java
The import part is happening in the clone method where each object needs to be cloned separately and added to the cloned parent object.
package com.admfactory.clone;
public class User implements Cloneable {
private String name;
private String email;
private int age;
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public Object clone() throws CloneNotSupportedException {
User user;
try {
user = (User) super.clone();
if (address != null)
user.address = (Address) address.clone();
} catch (CloneNotSupportedException e) { // this should never happen
System.out.println("CloneNotSupportedException thrown " + e);
return null;
}
return user;
}
@Override
public String toString() {
String result = "name: " + name + ", email: " + email + ", age: " + age;
if (address != null)
result += ", address: " + address;
return result;
}
}
Address.java
package com.admfactory.clone;
public class Address implements Cloneable {
private String street;
private String city;
private int number;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public Object clone() throws CloneNotSupportedException {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
System.out.println("CloneNotSupportedException thrown " + e);
throw new CloneNotSupportedException();
}
}
@Override
public String toString() {
return number + " " + street + ", " + city;
}
}
Usage
package com.admfactory.clone;
public class DeepCloneExample {
public static void main(String[] args) throws CloneNotSupportedException {
System.out.println("Object deep cloning example");
System.out.println();
/** defining one object */
User user1 = new User();
user1.setName("John Doe");
user1.setEmail("john@example.com");
user1.setAge(100);
Address address1 = new Address();
address1.setCity("London");
address1.setNumber(91);
address1.setStreet("Lambard");
user1.setAddress(address1);
System.out.println("User 1: ");
System.out.println(user1.toString());
System.out.println();
/**
* cloning the object - Notice the cast as the clone method from Cloneable
* returns Object
*/
User user2 = (User) user1.clone();
System.out.println("User 2: ");
System.out.println(user2.toString());
System.out.println();
/** changing the address for user 1 */
Address address2 = user1.getAddress();
address2.setCity("Glasgow");
address2.setNumber(12);
address2.setStreet("Peter");
user1.setAddress(address2);
System.out.println("User 1: ");
System.out.println(user1.toString());
System.out.println();
System.out.println("User 2: ");
System.out.println(user2.toString());
System.out.println();
}
}
Output
Object deep cloning example
User 1:
name: John Doe, email: john@example.com, age: 100, address: 91 Lambard, London
User 2:
name: John Doe, email: john@example.com, age: 100, address: 91 Lambard, London
User 1:
name: John Doe, email: john@example.com, age: 100, address: 12 Peter, Glasgow
User 2:
name: John Doe, email: john@example.com, age: 100, address: 91 Lambard, London
You can notice that changing the address object from the user1 object is not affecting the address object from the user2 object. In order to see the difference, you can comment the line 46-47 from User.java and run again the test application. You can see from the output that changing the address object from user1 is affecting the address object from user2, actually is the same object assigned to both user objects.