How to define the method clone in your Java class
In Java, a clone is the exact duplicate of an object and all its component objects. This duplicate, also knows as a deep copy, is completely distinct from the original object.
Typically, we only clone mutable objects. A mutable object is one that has public methods (such as set methods) that can change its state. Since it is safe to share an immutable object, cloning it is usually unnecessary.
The Object class contains a protected clone method that returns a copy of an object. This copy has shallow copies of any component objects. The method has the following header:
protected Object clone() throws CloneNotSupportedException
Since Object is an ancestor of all other Java classes, your class will inherit this protected clone method. However, a client of your class cannot invoke clone unless you override Object’s version with a public definition of clone.
Classes that define a clone method must implement the standard interface Cloneable, which has the following definition:
public interface Cloneable
{
} // end Cloneable
This interface is empty! It merely signals to the compiler that your class will override its inherited clone method.
Implementation
Below is a simple class of names that defines its own clone method. We’ll discuss it and then use it in another class:
public class NameDemo{public static void main(String[] args){// Create a Name objectName aName = new Name();aName.setName("Jamie", "Java");System.out.println("Object A's name is " + aName); // Calls toString// Clone the objectName theClone = (Name)aName.clone(); // Note the castSystem.out.println("The clone's name is " + theClone + "\n");// Change aName's name; see whether it changes the cloneaName.setName("Phantom", "O'Opera");System.out.println("Change A's name to " + aName + "\n");System.out.println("Did this change affect the clone?");System.out.println("The clone's name is " + theClone + "\n");// Change clone's name; see whether it changes aName's nametheClone.setName("Galaxy", "Moonbeam");System.out.println("Change theClone's name to " + theClone + "\n");System.out.println("Did this change affect A's name?");System.out.println("A's name is " + aName);} // End main} // End NameDemo
Study the code and notice the following key points about the Name class:
- The class header contains the
implements Cloneableclause Name’s public methodcloneoverridesObject’s protectedclonemethod- Both versions of
clonereturn an instance ofObject Name’scloneinvokesObject’sclonewith the expressionsuper.clone()super.clone()returns an instance ofObjectthat we cast toName- Because
Object’sclonemethod throws an exception,Name’s call to it is in atryblock. Thecatchblock is empty because we are definingcloneforName. Name’sclonewill not throw an exception, due to its use oftry/catchblocks; so, its client can call it withouttry/catchblocksName’sclonefinally copies the data fieldsfirstandlastand then returns the cloned object
We need to say more about the last bullet. We have provided code to make either shallow or deep copies of the fields first and last. You should try each version when you run the program. Because the fields are strings, and strings are clone copies them.
✏️ Note
Not all classes should have a public
clonemethod. Classes of immutable objects, for example, do not need aclonemethod. The standard classStringis such a class; it does not have a public methodclone.
! Programming Tip
A shallow copy of a data field that references an immutable object is typically sufficient for a clone, since it is usually safe to share an immutable object.
The Name object is mutable since it has a set method. Let’s use Name in the definition of another class, Person:
/** Name.java by F. M. CarranoA class of names, each containing a first name and a last name.*/public class Name implements Cloneable{private String first; // First nameprivate String last; // Last name/** Creates a default name whose first and last names are empty strings. */public Name(){first = "";last = "";} // End default constructorpublic Object clone(){Name theCopy = null;try{theCopy = (Name)super.clone(); // super.clone() returns an instance of Object}catch (CloneNotSupportedException e){ // This exception will not be thrown, since Name has a clone method.// But try/catch blocks are necessary!throw new Error(e.getMessage());}// Shallow copytheCopy.first = first;theCopy.last = last;/*// Deep copytheCopy.first = new String(first);theCopy.last = new String(last);*/return theCopy;} // End clone/** Sets the first and last names of this name object.@param firstName A string giving the name's first name.@param lastName A string giving the name's last name. */public void setName(String firstName, String lastName){first = firstName;last = lastName;} // End setName/** @return this name's first name as a string. */public String getFirstName(){return first;} // End getFirstName/** @return this name's last name as a string. */public String getLastName(){return last;} // End getLastName/** @return this name as a string. */public String toString(){return first + " " + last;} // End toString} // End Name
✏️ Note
If your class:
- Has a public method
clone- Does not extend another class or extends a class that does not define a
clonemethodYour class must:
- Implement the
Cloneableinterface- Define a public method (
clone) that overridesObject’s protected version
✏️ Note
If your class’s superclass defines its own public method (
clone), your class can override it instead of overridingObject’s protected method.