Tag Archives: Deep Cloning

Java : Shallow and Deep Object Cloning


Pr-requisite : Marker Interface in Java and Use, CloneNotSupportedException

In object oriented programming object copy or copy of object are possible many ways like copy constructor or copy of object. Here we will focus on both the ways for copy of object.

  • Shallow Copy or Shallow Cloning
  • Deep Copy or Deep Cloning

See also : Java : Shallow Cloning Vs Deep Cloning

Example of Shallow Cloning and Deep Cloning
Java : Shallow Cloning and Deep Cloning

Shallow Copy or Shallow Cloning

Whenever we use default implementation of copy of object means it create new instance of object and copies all the fields to the object new fields and if fields are non primitive or reference type variable to copy to new fields as reference of that non-primitive fields.

clone() method by default support shallow copy of object().  for implementing clone() method you have to implement Cloneable interface which is marker interface.

Shallow copy example by constructor

import java.util.Arrays;

public class Courses {
	String[] courseArr;
	// Shallow copy by constructor because in copy taking reference of object
	public Courses(String[] courseArr) {
		super();
		this.courseArr = courseArr;
	}
	@Override
	public String toString() {
		return "Courses [courseArr=" + Arrays.toString(courseArr) + "]";
	}

	public static void main(String[] str) {
	String[] courseArr = { "Math", "Physics", "Chemistry", "Hindi", "English" };
	Courses courses = new Courses(courseArr);
	System.out.println(courses);
	courseArr[2] = "Computer";//while changing in passed object will reflect on copy of object
	System.out.println(courses);
	}
}

Output


Courses [courseArr=[Math, Physics, Chemistry, Hindi, English]]
Courses [courseArr=[Math, Physics, Computer, Hindi, English]]

Shallow copy by clone method

In this example doing  shallow copy by clone method default way by implementing Cloneable interface and overriding clone() method which will by default make copy of object but here sub object course field in Student object will take reference of copied student object. It means if make any change on course object values will reflect same on copy object. clone method will always throw CloneNotSupportedException which always need to handle.

class Courses {
	String course1;
	String course2;
	String course3;

	public Courses(String course1, String course2, String course3) {
		this.course1 = course1;
		this.course2 = course2;
		this.course3 = course3;
	}
}

class Student implements Cloneable {
	int id;
	String name;
	Courses courses;

	public Student(int id, String name, Courses courses) {
		this.id = id;
		this.name = name;
		this.courses = courses;
	}

	// Default version of clone() method. It creates shallow copy of an object.
	// CloneNotSuportedException is checked exception always need to handle that
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

public class ShallowCopyInJava {
	public static void main(String[] args) {
		Courses science = new Courses("Physics", "Chemistry", "Math");
		Student student1 = new Student(1020, "Saurabh", science);
		Student student2 = null;

		try {
			// Creating a clone of student1 and assigning it to student2
			student2 = (Student) student1.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}

		// Printing the subject3 of 'student1'
		System.out.println(student1.courses.course3); // Output : Maths

		// Changing the course3 of 'student2'
		student2.courses.course3 = "Biology";

		// This change will be reflected in original student 'student1'
		System.out.println(student1.courses.course3); // Output : Biology
	}
}

Output


Math
Biology

Note: If class is having only primitive type values or Immutable object there is no difference between Shallow and Deep Cloning of object.

Deep Copy or Deep Cloning

Whenever we need own copy not to use default implementation (shallow copy or shallow cloning) of object. Always implement according to our need and make sure all the member of  class also having deep copied of fields.

If using cloneable interface and overriding clone() method of object class make sure member objects /reference objects also having deep copy of fields.

Deep copy example by constructor

import java.util.Arrays;

public class Courses {
	String[] courseArr;

	// Deep copy object because copy actual fields value not references
	public Courses(String[] courseArr) {
		super();
		if (courseArr != null) {
			this.courseArr = new String[courseArr.length];
			for (int i = 0; i <courseArr.length; i++) {
				this.courseArr[i] = courseArr[i];
			}
		}
	}

	@Override
	public String toString() {
		return "Courses [courseArr=" + Arrays.toString(courseArr) + "]";
	}

	public static void main(String[] str) {
		String[] courseArr = { "Math", "Physics", "Chemistry", "Hindi", "English" };
		Courses courses = new Courses(courseArr);
		System.out.println(courses);
		courseArr[2] = "Computer";// while changing in passed object will reflect on copy of object
		System.out.println(courses);
	}
}

Output


Courses [courseArr=[Math, Physics, Chemistry, Hindi, English]]
Courses [courseArr=[Math, Physics, Chemistry, Hindi, English]]

Deep copy by clone method
In this example doing  deep copy by clone method but handle copying each individual reference object copy separately as in Student class clone() method. It means if make any change on course object values will not reflect same on copy object. clone method will always throw CloneNotSupportedException which always need to handle.

class Courses implements Cloneable{
String course1;
String course2;
String course3;

public Courses(String course1, String course2, String course3) {
this.course1 = course1;
this.course2 = course2;
this.course3 = course3;
}

protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}
}

class Student implements Cloneable
{
int id;
String name;
Courses courses;

public Student(int id, String name, Courses courses)
{
this.id = id;
this.name = name;
this.courses = courses;
}

//Overriding clone() method to create a deep copy of an object.
//CloneNotSuportedException is checked exception always need to handle that

protected Object clone() throws CloneNotSupportedException
{
Student student = (Student) super.clone();
student.courses = (Courses) courses.clone();
return student;
}
}

public class DeepCopyInJava
{
public static void main(String[] args)
{
Courses science = new Courses("Physics", "Chemistry", "Math");
Student student1 = new Student(1020, "Saurabh", science);
Student student2 = null;

try
{
//Creating a clone of student1 and assigning it to student2
student2 = (Student) student1.clone();
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}

//Printing the subject3 of 'student1'
System.out.println(student1.courses.course3); //Output : Math
//Changing the subject3 of 'student2'
student2.courses.course3 = "Biology";
//This change will not be reflected in original student 'student1'
System.out.println(student1.courses.course3); //Output : Math
}
}

Output


Math
Math

Conclusion

Here you learn about Shallow and Deep copy  of object by constructor and implementing by clone() method of Cloneable Interface which is marker interface.

Advertisements

Java : Shallow Cloning Vs Deep Cloning


Pre-requisite : 

Below are  the list of differences between shallow cloning and deep cloning in java.

Example of Shallow Cloning and Deep Cloning
Java : Shallow Cloning and Deep Cloning

Shallow Cloning

  • Cloned Object and original object are not 100% disjoint.
  • Any changes made to cloned object will be reflected in original object or vice versa.
  • Default version of clone method creates the shallow copy of an object.
  • Shallow copy is preferred if an object has only primitive fields.
  • Shallow copy is fast and also less expensive.

Example: Shallow Cloning Example

Deep Cloning

  • Cloned Object and original object are 100% disjoint.
  • Any changes made to cloned object will not be reflected in original object or vice versa.
  • To create the deep copy of an object, you have to override clone method.
  • Deep copy is preferred if an object has references to other objects as fields.
  • Deep copy is slow and very expensive.

Example: Deep Cloning Example

[Solved] CloneNotSupportedException


java.lang.CloneNotSupportedException throws when object’s class does not implement the cloneable interface and  clone method in class Object has been called to clone an object.
Some applications that override the clone method can also throw this exception to indicate that an object could not or should not be cloned.

Cloneable is marker interface which is not having any method to implement. When implement marker interface in class it indicate to JVM how to treat with this objects.
For more info about marker interface , it’s type and how to create check below link.

Marker Interface in Java, Use and Custom Marker Interface

clone() is protected method of object class which is super class of all the classes. if need to use clone() method have to override it .

Constructors :

  • CloneNotSupportedException()

Create a CloneNotSupportedException object with no detail message.

  • CloneNotSupportedException(String message)

Create a CloneNotSupportedException object with  exception detail message.

Example

In below example creating clone object of Employee class from object there is no any compile time error because we have override clone method of Object Class in Employee class but it will throw CloneNotSupportedException while execution because as per

Contract : if cloneable interface is implemented then only clone method will call otherwise  JVM will throw CloneNotSupportedException.

Here we are doing Shallow cloning of object. For more info on shallow and deep cloning follow below link.

Employee Class

public class Employee {
private String firstName;
private String lastName;
private int age;
private double salary;
private Address address;

public Employee(String firstName, String lastName, int age, double salary, Address address) {
	super();
	this.firstName = firstName;
	this.lastName = lastName;
	this.age = age;
	this.salary = salary;
	this.address = address;
}
public String getFirstName() {
	return firstName;
}
public void setFirstName(String firstName) {
	this.firstName = firstName;
}
public String getLastName() {
	return lastName;
}
public void setLastName(String lastName) {
	this.lastName = lastName;
}
public int getAge() {
	return age;
}
public void setAge(int age) {
	this.age = age;
}
public double getSalary() {
	return salary;
}
public void setSalary(double salary) {
	this.salary = salary;
}
public Address getAddress() {
	return address;
}
public void setAddress(Address address) {
	this.address = address;
}

@Override
public String toString() {
	return "Employee [firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + ", salary=" + salary
			+ ", address=" + address + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
	return super.clone();
}

}


Address Class


public class Address {
	private String addressLine1;
	private String city;
	private String state;
	private String contry;
	private String pincode;

	public Address(String addressLine1, String city, String state, String contry, String pincode) {
		super();
		this.addressLine1 = addressLine1;
		this.city = city;
		this.state = state;
		this.contry = contry;
		this.pincode = pincode;
	}

	public String getAddressLine1() {
		return addressLine1;
	}

	public void setAddressLine1(String addressLine1) {
		this.addressLine1 = addressLine1;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public String getContry() {
		return contry;
	}

	public void setContry(String contry) {
		this.contry = contry;
	}

	public String getPincode() {
		return pincode;
	}

	public void setPincode(String pincode) {
		this.pincode = pincode;
	}

	@Override
	public String toString() {
		return "Address [addressLine1=" + addressLine1 + ", city=" + city + ", state=" + state + ", contry=" + contry
				+ ", pincode=" + pincode + "]";
	}

}


Test for ClassNotSupportedException


public class CloneExample {

	public static void main(String[] args) {
		Address address = new Address("Next to Metro Station", "Noida", "UP", "India", "201301");
		Employee employee = new Employee("Saurabh", "Gupta", 30, 50000, address);
		System.out.println("Employee Object Before Clone :");
		System.out.println(employee);
		try {
                        System.out.println("Employee Object After Clone :");
			Employee employeeCopy = (Employee) employee.clone();

			System.out.println(employeeCopy);
		} catch (CloneNotSupportedException ex) {
			ex.printStackTrace();
		}

	}

}


Output

Employee Object Before Clone :
Employee [firstName=Saurabh, lastName=Gupta, age=30, salary=50000.0, address=Add
ress [addressLine1=Next to Metro Station, city=Noida, state=UP, contry=India, pi
ncode=201301]]
Employee Object After Clone :
java.lang.CloneNotSupportedException: Employee
	at java.lang.Object.clone(Native Method)
	at Employee.clone(Employee.java:55)
	at CloneExample.main(CloneExample.java:11)

Solutions :

To solve this CloneNotSupportedException we have to implement cloneable interface in Employee class as below and run this program again.

public class Employee implements Cloneable<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>{

}

Summary :

  • Explain about CloneNotSupportedException by example and how it happen.
  • Constructors of CloneNotSupportedException.
  • How to fix CloneNotSupportedException.
  • Cloneable Marker Interface.

References :

https://docs.oracle.com/javase/8/docs/api/java/lang/CloneNotSupportedException.html