Copy constructors
Defensive copying
Factory methods
clone
.
clone
is very tricky to implement correctly in all circumstances,
nearly to the point of being pathologicalclone
, and are much
easier to implementclone
, then
your subclass must implement clone
as well. The quickest solution is
for your subclass to simply throw an exception.
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 colour, Date bestBeforeDate) { super(); this.colour = colour; //defensive copy needed for this mutable object this.bestBeforeDate = new Date(bestBeforeDate.getTime()); } public abstract void ripen(); public String getColour() { return colour; } public Date getBestBeforeDate() { //return defensive copy of this mutable object return new Date(bestBeforeDate.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.bestBeforeDate = new Date(this.bestBeforeDate.getTime()); return result; } // PRIVATE /** Strings are always immutable. */ private String colour; /** * In new code, you should use LocalDate, not java.util.Date! * Here, java.util.Date is used only to make a point regarding mutable fields. * * 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 bestBeforeDate; }Here is the subclass, with its
clone
method disabled.
import java.util.Date; public final class Apple extends Fruit { public Apple(String colour, Date bestBeforeDate) { super(colour, bestBeforeDate); } 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(); } }