Name: jl125535 Date: 01/10/2003
FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)
A DESCRIPTION OF THE PROBLEM :
Java's current clone mechanism is unsatisfactory. It
requires too much development effort, and goes wrong too
many times, both in 3rd party code and in the libraries.
Looking through the bug list reveals many cases where minor
bugs in cloning have been reported and fixed, throughout
the life of Java. Some bugs will admittedly never be fixed,
such as the cloning of inner classes. Some well-respected
sources suggest using a duplicate() method instead. A new
approach is needed.
I suggest that cloning should become a language level
feature, on a par with constructors. The syntax for
cloning an object would be:
Thing a = new Thing();
Thing b = clone a;
There would also be the option to clone with arguments.
Thing c = clone a(xyz);
Like constructors, this feature would be closely managed by
the VM. Some VMs may choose to implement lazy cloning,
others may use optimizations i'd never think of.
The syntax for writing a clonable class will look something
like this:
class Doodad extends Thing implements Cloneable {
Wotsit wotsit = new Wotsit();
public Doodad() {
super(wotsit);
}
public clone Doodad() {
clone wotsit;
clone super(wotsit);
}
}
The variable wotsit is, under normal circumstances,
assigned along with the constructor as a new Wotsit(). But
when the object is cloned, its wotsit is a clone of the
template's wotsit.
When you clone a child from within a clone method, the
meaning is different from simply calling child.clone().
Cloning one object may involve cloning a collection of
children, and their children and grandchildren. Like
serialization, the new clone would allow for only cloning
the same object once, especially when dealing with circular
references and shared objects.
Consider this case:
class TreeNode
{
final TreeNode parent;
Set<TreeNode> children;
IconSupplier supplier;
public TreeNode(TreeNode parent) {
this.parent = parent;
this.supplier = parent.supplier;
}
public TreeNode getParent() {
return parent;
}
public Icon getIcon() {
return supplier.getIcon(this);
}
public void addChild(TreeNode child) {
children.add(child);
}
public Iterator iterator() {
return children.iterator();
}
public clone TreeNode() {
clone children;
clone supplier;
}
}
The clone method clones the children, but does not clone
the parent. Note that it says to clone the supplier, and
the supplier is referenced in many parts of the tree, and
yet it only clones that supplier once in the life of a
clone operation. This allows you to clone part of the tree
and do something to its icon supplier, without creating 500
suppliers.
REPRODUCIBILITY :
This bug can be reproduced always.
CUSTOMER WORKAROUND :
Use the existing clone mechanism, with lots checks for the
issues it raises. Referential integrity, specifically, is
nasty.
(Review ID: 178968)
======================================================================