Cloning

From Suhrid.net Wiki
Jump to navigationJump to search
  • There is no syntactical way to copy an object in Java. The assignment operator just's duplicates the reference.
  • Cloning and the clone() method provides a way to perform such copying.
  • The object class has a clone() method which is protected. So it has to be overriden in the implementing class in order to use it.
  • The default implementation can call super.clone() - but this means the class has to implement the Cloneable marker interface.
  • Object's clone() performs what is called a "shallow" copy - typically one level of copying.
  • Deep copying means copying containing referenced objects as well. Of course we can keep going deeper, so "shallow" and "deep" are subjective terms and it is upto developer to implement.
  • See below example, the default clone() makes only a shallow copy of Foo, copying the integer and String but does not copy the Bar reference.
package net.suhrid;

public class RefTest {
	
	private class Bar {
		
		private float f;
		
		public Bar(float f) {
			this.f = f;
		}
		
		public String toString() {
			return "f= " + f;
		}
	}
	
	private class Foo implements Cloneable {
		
		private int i;
		private String str;
		private Bar b;
		
		public Foo() {
		}
		
		public Foo(int i, String str, Bar b) {
			this.i = i;
			this.str = str;
			this.b = b;
		}
		
		public void setI(int i) {
			this.i = i;
		}

		public void setStr(String str) {
			this.str = str;
		}

		public void setB(Bar b) {
			this.b = b;
		}
		
		public Bar getB() {
			return b;
		}

		public String toString() {
			return "i: " + i + ";" + "str: " + str + ";bar : " + b;
		}
		
		public Object clone() throws CloneNotSupportedException {
			return super.clone();
		}
		
	}

	public static void main(String[] args) {
		RefTest rt = new RefTest();
		rt.go();
	}
	
	private void go() {
		
		Bar b1 = new Bar(4.2f);
		Foo f1 = new Foo(42, "Fanta", b1);
		Foo f2 = null;
		try {
			System.out.println("Original: " + f1);
			f2 = (Foo) f1.clone(); 
			System.out.println("Clone: " + f2);
			System.out.println("Same bar ? " + (f1.getB() == f2.getB())); //Prints true
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}
}
  • To fix this, we have to explicitly clone Bar within Foo's clone method - aka deep copy.
public Object clone() throws CloneNotSupportedException {
			Foo clone = new Foo();
			clone.setI(i);
			clone.setStr(str);
			clone.setB((Bar)b.clone());
			return clone;
}