What does super.clone() do?

  Pi Ke        2015-01-07 05:25:52       31,188        0    

Object class has a protected clone() method declared to make it possible for all classes make a clone of itself when needed. The clone() is often used when a new instance of the class is needed while at the same time to maintain the same state as the original object. Any class which wants to have clone enabled has to implement the marker interface Cloneable.

If a class which implements Cloneable doesn't override the Object.clone() method, the Object.clone() method will be called to just make a binary copy of the original, which amounts to a shallow clone, with all the referenced objects staying the same. This means all the references including private references in the original object will be copied to the cloned object. The Object.clone() is a native method and it does a shallow copy. For more infor, please see the Object.clone() source code.

If a class which implements Cloneable does override the Object.clone() method, usually a super.clone() will be called first to make a binary copy of the original object and then deep copy will be performed accordingly based on the binary copy. See below example:

public class CloneTest implements Cloneable {
	private byte[] a = {1, 2, 3, 4, 5};
	private byte[] b = {5, 4, 3, 2, 1};
	
	public CloneTest clone(){
		CloneTest that = null;
		try{
			that = (CloneTest)super.clone();		//Make a binary copy
			that.b = this.b.clone();				//Do customized operation
			return that;
		} catch (CloneNotSupportedException ex){
			ex.printStackTrace();
		}
		return that;
	}
	
	public byte[] getA(){
		return this.a;
	}
	
	public byte[] getB(){
		return this.b;
	}
	
	public static void main(String[] args){
		CloneTest original = new CloneTest();
		CloneTest cloned = original.clone();
		
		//About original.a
		System.out.println("original.a == cloned.a : " + (original.getA() == cloned.getA()));
		System.out.println("cloned.a[2] = " + cloned.getA()[2]);
		//Modify original.a[2]
		original.getA()[2] = 10;
		System.out.println("cloned.a[2] = " + cloned.getA()[2]);
		
		//About original.b
		System.out.println("original.b == cloned.b : " + (original.getB() == cloned.getB()));
		System.out.println("cloned.b[2] = " + cloned.getB()[2]);
		//Modify original.b[2]
		original.getB()[2] = 10;
		System.out.println("cloned.b[2] = " + cloned.getB()[2]);
	}
}

Are you confused about the super.clone() method? Why does the super.clone() can be cast to CloneTest? Usually super means the parent class which means we will only get a copy of an super class instance, right? Then the object is downcast to the object which should not be correct, right? The fact is that the super.clone() will return an object that calls the super.clone() method. To understand why, please read carefully about what the Object.clone() method does. The implementation of clone() in Object checks if the actual class implements Cloneable, and creates an instance of that actual class. This means below relationship should be correct:

x.clone() != x
x.clone().getClass() == x.getClass()

Another important note about clone() is that any mutable object should be explicitly cloned when overriding the clone() method. The above example has a bug which would cause issue. the mutable object array a is not explicitly cloned so the cloned object will share the same array reference with the original object  If an element in array a is changed, this change will reflect on the cloned object as well.

The result from the program execution shows this exact behavior :

original.a == cloned.a : true
cloned.a[2] = 3
cloned.a[2] = 10
original.b == cloned.b : false
cloned.b[2] = 3
cloned.b[2] = 3

From the output, original.a == cloned.a : true means the reference to array a is the same in original and cloned object. And also cloned.a[2] is changed to 10.

To mitigate the problem, need to add that.a = this.a.clone(); in the clone(0 method.

One general tip about using clone() is that paying extremely care when overriding clone() method. Check every mutable object in the class and see whether there is a need to make a deep copy of it. Don't use clone() whenever possible.

JAVA  CLONEABLE  SUPER.CLONE()  CLONE 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

Delete my browser history