Now consider what happens when future code invokes first.pop(), followed by first.push(17).
The top element in the stack first will change from 9 to 17 , which is expected. The programmer will
probably be surprised, however, to see that the top element of second will also change to 17 because there
is only one array that is shared by the two stacks.
The solution is to override clone to make a copy of the array:
public IntegerStack clone() {
try {
IntegerStack nObj = (IntegerStack) super.clone();
nObj.buffer = buffer.clone();
return nObj;
} catch (CloneNotSupportedException e) {
// Cannot happen -- we support
// clone, and so do arrays
throw new InternalError(e.toString());
}
}
First the clone method invokes super.clone. This invocation is very important because the superclass
may be working around its own problem of shared objects. If you do not invoke the superclass's method, you
solve your own cloning problem but you may create another one. Furthermore, super.clone will
eventually invoke the method Object.clone, which creates an object of the correct type. If the
IntegerStack implementation of clone used new to create an IntegerStack object, it would be
incorrect for any object that extended IntegerStack. The extended class's invocation of super.clone
would give it an IntegerStack object, not an object of the correct, extended type. The return value of
super.clone is then cast to an IntegerStack reference.
Object.clone initializes each field in the new clone object by assigning it the value from the same field of
the object being cloned. You then need only write special code to deal with fields for which copying the value
is incorrect. IntegerStack.clone doesn't need to copy the top field, because it is already correct from
the "copy values" default. It must, however, make a copy of the buffer array, which is done by cloning the
arrayall arrays can be cloned, with clone returning a reference of the same type as the array reference on
which clone was invoked.
With the specialized clone method in place, the example code now creates memory that looks like this:
Cloning is an alternative form of construction but is not recognized as construction by the system. This means
that you have to be wary of using blank finals (see page 46) that can be set only in constructors. If the value of
the final field should be a copy of the value in the object being cloned, then there is no problem since