Avoid clone
Avoid implementing clone.
- clone is very tricky to implement correctly in all circumstances, nearly to the point of being pathological
- the importance of copying objects will always remain, since object fields often need to be defensively copied
- copy constructors and static factory methods provide an alternative to clone, and are much easier to implement
Example
This example shows a superclass with a typical implementation of clone,
and a subclass which has disabled its clone method.
import java.util.Date; public abstract class Fruit implements Cloneable { public Fruit( String aColour, Date aBestBeforeDate ) { super(); fColour = aColour; //defensive copy needed for this mutable object fBestBeforeDate = new Date( aBestBeforeDate.getTime() ); } public abstract void ripen(); public String getColour() { return fColour; } public Date getBestBeforeDate() { //return defensive copy of this mutable object return new Date ( fBestBeforeDate.getTime() ); } /** * Implement clone as follows * <ul> * <li>the class declaration "implements Cloneable" (not needed if already * declared in superclass) * <li>declare clone method as public * <li>if the class is final, clone does not need to throw CloneNotSupportedException * <li>call super.clone and cast to this class * <li>as in defensive copying, ensure each mutable field has an independent copy * constructed, to avoid sharing internal state between objects * </ul> */ @Override public Object clone() throws CloneNotSupportedException { //get initial bit-by-bit copy, which handles all immutable fields Fruit result = (Fruit)super.clone(); //mutable fields need to be made independent of this object, for reasons //similar to those for defensive copies - to prevent unwanted access to //this object's internal state result.fBestBeforeDate = new Date( this.fBestBeforeDate.getTime() ); return result; } /// PRIVATE //// /** * Strings are always immutable. */ private String fColour; /** * Date is a mutable object. In this class, this object field is to be treated * as belonging entirely to this class, and no user of this class is * to be able to directly access and change this field's state. */ private Date fBestBeforeDate; }
Here is the subclass, with its clone method disabled.
import java.util.Date; public final class Apple extends Fruit { public Apple( String aColour, Date aBestBeforeDate ) { super( aColour, aBestBeforeDate ); } public void ripen() { //empty implementation of abstract method } /** * The Apple subclass does not support clone. */ @Override public final Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } }
See Also :
Would you use this technique?
Add your comment to this Topic :
|