Feedback
This example shows what you must do to accomplish a deep copy when
dealing with a composed object:
//: appendixa:DeepCopy.java
// Cloning a composed object.
// {Depends: junit.jar}
import junit.framework.*;
class DepthReading implements Cloneable {
private double depth;
public DepthReading(double depth) { this.depth = depth; }
public Object clone() {
Object o = null;
try {
o = super.clone();
} catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
public double getDepth() { return depth; }
public void setDepth(double depth){ this.depth = depth; }
public String toString() { return String.valueOf(depth);}
}
class TemperatureReading implements Cloneable {
private long time;
private double temperature;
public TemperatureReading(double temperature) {
time = System.currentTimeMillis();
this.temperature = temperature;
}
public Object clone() {
Object o = null;
try {
o = super.clone();
} catch(CloneNotSupportedException e) {
e.printStackTrace();
1064
Thinking in Java
www.BruceEckel.com
}
return o;
}
public double getTemperature() { return temperature; }
public void setTemperature(double temperature) {
this.temperature = temperature;
}
public String toString() {
return String.valueOf(temperature);
}
}
class OceanReading implements Cloneable {
private DepthReading depth;
private TemperatureReading temperature;
public OceanReading(double tdata, double ddata) {
temperature = new TemperatureReading(tdata);
depth = new DepthReading(ddata);
}
public Object clone() {
OceanReading o = null;
try {
o = (OceanReading)super.clone();
} catch(CloneNotSupportedException e) {
e.printStackTrace();
}
// Must clone references:
o.depth = (DepthReading)o.depth.clone();
o.temperature =
(TemperatureReading)o.temperature.clone();
return o; // Upcasts back to Object
}
public TemperatureReading getTemperatureReading() {
return temperature;
}
public void setTemperatureReading(TemperatureReading tr){
temperature = tr;
}
public DepthReading getDepthReading() { return depth; }
public void setDepthReading(DepthReading dr) {
this.depth = dr;
}
public String toString() {
return "temperature: " + temperature +
Appendix A: Passing & Returning Objects
1065
", depth: " + depth;
}
}
public class DeepCopy extends TestCase {
public DeepCopy(String name) { super(name); }
public void testClone() {
OceanReading reading = new OceanReading(33.9, 100.5);
// Now clone it:
OceanReading clone = (OceanReading)reading.clone();
TemperatureReading tr = clone.getTemperatureReading();
tr.setTemperature(tr.getTemperature() + 1);
clone.setTemperatureReading(tr);
DepthReading dr = clone.getDepthReading();
dr.setDepth(dr.getDepth() + 1);
clone.setDepthReading(dr);
assertEquals(reading.toString(),
"temperature: 33.9, depth: 100.5");
assertEquals(clone.toString(),
"temperature: 34.9, depth: 101.5");
}
public static void main(String[] args) {
junit.textui.TestRunner.run(DeepCopy.class);
}
} ///:~
DepthReading and TemperatureReading are quite similar; they
both contain only primitives. Therefore, the clone( ) method can be quite
simple: it calls super.clone( ) and returns the result. Note that the
clone( ) code for both classes is identical. Feedback
OceanReading is composed of DepthReading and
TemperatureReading objects and so, to produce a deep copy, its
clone( ) must clone the references inside OceanReading. To
accomplish this, the result of super.clone( ) must be cast to an
OceanReading object (so you can access the depth and temperature
references). Feedback
A deep copy with ArrayList
Let’s revisit Cloning.java from earlier in this appendix. This time the
Int2 class is cloneable, so the ArrayList can be deep copied:
1066
Thinking in Java
www.BruceEckel.com
//: appendixa:AddingClone.java
// You must go through a few gyrations
// to add cloning to your own class.
import com.bruceeckel.simpletest.*;
import java.util.*;
class Int2 implements Cloneable {
private int i;
public Int2(int ii) { i = ii; }
public void increment() { i++; }
public String toString() { return Integer.toString(i); }
public Object clone() {
Object o = null;
try {
o = super.clone();
} catch(CloneNotSupportedException e) {
System.err.println("Int2 can't clone");
}
return o;
}
}
// Inheritance doesn't remove cloneability:
class Int3 extends Int2 {
private int j; // Automatically duplicated
public Int3(int i) { super(i); }
}
public class AddingClone {
private static Test monitor = new Test();
public static void main(String[] args) {
Int2 x = new Int2(10);
Int2 x2 = (Int2)x.clone();
x2.increment();
System.out.println("x = " + x + ", x2 = " + x2);
// Anything inherited is also cloneable:
Int3 x3 = new Int3(7);
x3 = (Int3)x3.clone();
ArrayList v = new ArrayList();
for(int i = 0; i < 10; i++ )
v.add(new Int2(i));
System.out.println("v: " + v);
|