Difference between revisions of "Cloning"
From Suhrid.net Wiki
Jump to navigationJump to search (Created page with "* 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 ...") |
|||
(3 intermediate revisions by the same user not shown) | |||
Line 3: | Line 3: | ||
* 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 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. | * 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. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | 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(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * To fix this, we have to explicitly clone Bar within Foo's clone method - aka deep copy. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | public Object clone() throws CloneNotSupportedException { | ||
+ | Foo clone = new Foo(); | ||
+ | clone.setI(i); | ||
+ | clone.setStr(str); | ||
+ | clone.setB((Bar)b.clone()); | ||
+ | return clone; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> |
Latest revision as of 16:36, 22 June 2012
- 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;
}