Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Language: Java Language
Expertise: Beginner
Jan 8, 1999

Cloning: Shallow vs. Deep Copies

Question:
I am seeking to clone an object that contains an array of the type float[][] which in turn contains primitive types. Using super.clone() and a clonable interface in the class has resulted in a shallow copy. Do I need to make the array an array of Objects and deep copy?

Answer:
The default clone() method is implemented in native code in the fundamental java.lang.Object class. It performs the equivalent of a memcpy() operation, which in C would cause any pointers to be copied directly. The effect in Java is for all references to point to the same objects and for primitive types to be copied. This results in a shallow copy. A deep copy is where true copies of all references are made by creating a new object and performing a deep copy of the original object. If you want clone() to perform a deep copy, you have to implement it yourself. The following example makes clear the difference between a deep copy and a shallow copy, as well as showing that the default clone() method copies references, rather than creating new objects with equivalent values.

public final class CloneExample {

    public static class ShallowCopy implements Cloneable {
	// I'm using an int array so I don't have to do print formatting.
	public int[][] data = {
	    { 0, 1 },
	    { 1, 0 }
	};

	public String toString() {
	    StringBuffer buffer = new StringBuffer();
	    int row, column, d[];

	    for(row = 0; row < data.length; ++row) {
		d = data[row];
		for(column = 0; column < d.length; ++column) {
		    buffer.append(d[column]);
		    buffer.append(' ');
		}
		buffer.append('\n');
	    }
	    return buffer.toString();
	}

	public void setValue(int row, int column, int value) {
	    data[row][column] = value;
	}

	// Performs a default shallow copy
	public Object clone() throws CloneNotSupportedException {
	    return super.clone();
	}
    }

    public static class DeepCopy extends ShallowCopy {
	// Explicitly performs a deep copy
	public Object clone() throws CloneNotSupportedException {
	    int row;
	    DeepCopy copy = new DeepCopy();
	    copy.data = new int[data.length][];

	    for(row=0; row < data.length; ++row) {
		copy.data[row] = new int[data[row].length];
		System.arraycopy(data[row], 0, copy.data[row], 0,
				 data[row].length);
	    }
	    return copy;
	}
    }


    public static final void main(String[] args) {
	ShallowCopy shallow = new ShallowCopy();
	ShallowCopy shallowClone;
	DeepCopy deep = new DeepCopy();
	DeepCopy deepClone;

	System.out.println("ShallowCopy Original Data");
	System.out.println(shallow.toString());

	try {
	    shallowClone = (ShallowCopy)shallow.clone();
	} catch(CloneNotSupportedException e) {
	    e.printStackTrace();
	    return;
	}

	// The clone should have the same data
	System.out.println("ShallowCopy Clone Data");
	System.out.println(shallowClone.toString());

	// In a shallow copy, if we alter the original data, it should
	// be reflected in the cloned data.
	shallow.setValue(0, 1, 0);
	shallow.setValue(1, 0, 0);

	System.out.println("ShallowCopy Original Data");
	System.out.println(shallow.toString());

	System.out.println("ShallowCopy Clone Data");
	System.out.println(shallowClone.toString());

	// Why was the data identical?  Because the shallow copy caused
	// the clone data to reference the same array as the original.
	if(shallow.data == shallowClone.data)
	    System.out.println(
	       "The original array and cloned array are the same object!");
	else
	    System.err.println("Unexpected result!");


	System.out.println("DeepCopy Original Data");
	System.out.println(deep.toString());

	try {
	    deepClone = (DeepCopy)deep.clone();
	} catch(CloneNotSupportedException e) {
	    e.printStackTrace();
	    return;
	}

	// The clone should have the same data
	System.out.println("DeepCopy Clone Data");
	System.out.println(deepClone.toString());

	// In a deep copy, if we alter the original data, it should
	// NOT be reflected in the cloned data.
	deep.setValue(0, 1, 0);
	deep.setValue(1, 0, 0);

	System.out.println("DeepCopy Original Data");
	System.out.println(deep.toString());

	System.out.println("DeepCopy Clone Data");
	System.out.println(deepClone.toString());

	// The data was not identical because the deep copy created
	// an entirely new array.
	if(deep.data != deepClone.data)
	    System.out.println(
	       "The original array and cloned array are NOT the same object!");
	else
	    System.err.println("Unexpected result!");
    }
}
DevX Pro
 
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date