THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

3.9.2. Correct Cloning


Objects of most classes can be cloned in principle. Even if your class does not support the Cloneable
interface, you should ensure that its clone method is correct. In many classes, the default implementation of
clone will be wrong because it duplicates a reference to an object that shouldn't be shared. In such cases,
clone should be overridden to behave correctly. The default implementation assigns each field from the
source to the same field in the destination object.


If, for example, an object has a reference to an array, a clone of one of the objects will refer to the same array.
If the array holds read-only data, such a shared reference is probably fine. But if it is a list of objects that
should be distinct for each of your objects, you probably don't want the clone's manipulation of its own list to
affect the list of the original source object, or vice versa.


Here is an example of the problem. Suppose you have a simple integer stack class:


public class IntegerStack implements Cloneable { // dangerous
private int[] buffer;
private int top;


public IntegerStack(int maxContents) {
buffer = new int[maxContents];
top = -1;
}


public void push(int val) {
buffer[++top] = val;
}
public int pop() {
return buffer[top--];
}


public IntegerStack clone() {
try {
return (IntegerStack) super.clone();
} catch (CloneNotSupportedException e) {
// Cannot happen -- we support clone
throw new InternalError(e.toString());
}
}


// ...
}


Here we override clone to make it public, but we use the default implementation from the Object class.


Now let's look at some code that creates an IntegerStack object, puts some data onto the stack, and then
clones it:


IntegerStack first = new IntegerStack(2);
first.push(2);
first.push(9);
IntegerStack second = first.clone();


With the default clone method, the data in memory will look something like this:

Free download pdf