Java Cloning Tutorial, Shallow Copy and Deep Copy
What is cloning
Cloning is the process of creating another copy of an object. A clone of an object can be created by calling the clone() method of the class implementing the Cloneable interface.
2. Types of Cloning
3. clone method return type
4. Cloning alternatives
5. Cloning interview questions
6. References
By default, all classes inherit the clone() method from Object class but to actually clone an object of a class, implementation of the Cloneable interface is mandatory. If the clone() method is called on an object without its class implementing the Cloneable interface then a CloneNotSupported exception is thrown. The clone() method inherited from Object class can be overridden to make the cloning operation customized. The Cloneable interface is a marker/tag interface like Serializable interface.
Importance of Cloneable
Here is the code and output when you try to call the clone() method without implementing the Cloneable interface:
package example.java;
public class Test {
public static void main(String[] args) {
Test b1 = new Test();
try {
Test b2 = (Test)b1.clone();
}catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
Output:
java.lang.CloneNotSupportedException: example.java.Test
at java.lang.Object.clone(Native Method)
at example.java.Test.main(Test.java:8)
Types of Cloning
Cloning can be of two types viz. shallow cloning and deep cloning. A shallow copy is what the default implementation of the clone method in Object class returns. For deep cloning, the clone() method needs to be overridden. Let us understand both of them with examples.
Shallow Cloning:
The default behavior of clone() method inherited from the Object class is known as shallow cloning. Here is an example to showcase shallow cloning.
package example.java;
public class Test implements Cloneable {
int a = 10;
StringBuffer b = new StringBuffer("abc");
public static void main(String[] args) {
Test b1 = new Test();
try {
Test b2 = (Test)b1.clone();
System.out.println("Before");
System.out.println("b1.a=" + b1.a + " b1.b=" + b1.b);
System.out.println("b2.a=" + b2.a + " b2.b=" + b2.b);
b1.a=20;
b1.b.append("def");
System.out.println("After");
System.out.println("b1.a=" + b1.a + " b1.b=" + b1.b);
System.out.println("b2.a=" + b2.a + " b2.b=" + b2.b);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
Output:
Before
b1.a=10 b1.b=abc
b2.a=10 b2.b=abc
After
b1.a=20 b1.b=abcdef
b2.a=10 b2.b=abcdef
Here we can see that changing the value of primitive member variable a, changes the value of b1 only and not b2 which means that both have their own copy of primitive data type. But changing the object being pointed by reference variable b brings changes in both the original object and the cloned object which means that both are using the same underlying object b. This behavior of using the same reference variable for both the original and cloned object is known as shallow cloning.
Deep Cloning:
Let us now see how deep cloning can be achieved by overriding the clone() method:
public class Test implements Cloneable {
int a = 10;
StringBuffer b = new StringBuffer("abc");
protected Object clone() throws CloneNotSupportedException {
return new Test();
}
public static void main(String[] args) {
Test b1 = new Test();
try {
Test b2 = (Test)b1.clone();
System.out.println("Before");
System.out.println("b1.a=" + b1.a + " b1.b=" +
b1.b);
System.out.println("b2.a=" + b2.a + " b2.b=" +
b2.b);
b1.a=20;
b1.b.append("def");
System.out.println("After");
System.out.println("b1.a=" + b1.a + " b1.b=" +
b1.b);
System.out.println("b2.a=" + b2.a + " b2.b=" +
b2.b);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
Output:
Before
b1.a=10 b1.b=abc
b2.a=10 b2.b=abc
After
b1.a=20 b1.b=abcdef
b2.a=10 b2.b=abc
The output clearly shows that deep cloning results in different member reference objects for the two classes.
clone method return type
As discussed above, the syntax of clone method in Object class is:
protected native Object clone() throws CloneNotSupportedException;
Since the return type of clone method is of type Object, any one invoking the clone method on a class would need to type cast it back to the appropriate class before making use of the cloned object. Typecasting has its own issues and complexities.
If you are using Java SE 5.0 in your project then using the co-variant return types is the best thing you can do to avoid type casting issues. You can read on how to define co-variant methods (in terms of overriding) in our co-variant return types tutorial.
Cloning alternatives
The purpose of cloning is to create a duplicate object. There are ways provided by Java API’s to achieve the same result differently. The following are the approaches which can act as alternative to clone method approach:
- 1) De-serialization: When you de-serialize an object, the constructor of the Serializable class and any of the Serializable super class is not invoked. This is an alternative to create exact replicas of objects. But if reading the object state from files, this approach would perform less efficiently than the clone method approach.
- 2) Copy Constructor: In this method, you have a constructor which accepts the same class object as argument. The constructor creates a copy of the passed argument and then returns a new copy of the object.
Cloning interview questions
Beginners to Java programming are not much comfortable to the concept of cloning. Here are some FAQ which can also server as a good resource for interview questions
1) What is the difference between Shallow copy deep copy?
Ans: Read the above section on difference between shallow and deep cloning to get the detailed difference between the two.
2) How would you prevent cloning of singleton class?
Ans: Since Singleton classes shouldn’t allow more than two instances of itself being created, some steps may be required to be taken depending upon how the singleton has been implemented.
a) We should never make a singleton class Cloneable explicitly.
b) Better provide and implementation of clone method in the Singleton class and throw the CloneNotSupportedException object from this overridden method.
3) Can we clone arrays?
Ans: Yes, arrays in Java also represent an Object. Any array object can be cloned by using the clone method. The implementation of clone method for arrays is written inside the JVM.
int[] ints = new int[] { 123, 234 };
int[] intsClone = (int[]) ints.clone();
4) Why don’t collection classes implement the Cloneable interface?
Ans: The Collection class can contain huge amount of data and are a means to store data temporarily in the memory. Since the scope in which collection classes can be used is very large, it was decided to keep collection classes as non-cloneable by default and provide other methods like addAll, contains etc.
5) How would you clone the objects of a class depending upon some condition?
Ans: Since we shall need to override the clone method in the class, we can add the condition in the clone method and return a result after executing the condition statement.
6) What are the security implications of using the clone method?
Ans: a) The private members also get clone by default.
b) Interleaving issues can arise in multi-threaded environments.
References
1. Why we use clone() method in java?
2. Object as a Superclass






2 Comments on “Java Cloning Tutorial, Shallow Copy and Deep Copy”
Trackbacks