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.
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:
implements Cloneable
clauseName
’s public method clone
overrides Object
’s protected clone
methodclone
return an instance of Object
Name
’s clone
invokes Object
’s clone
with the expression super.clone()
super.clone()
returns an instance of Object
that we cast to Name
Object
’s clone
method throws an exception, Name
’s call to it is in a try
block. The catch
block is empty because we are defining clone
for Name
.Name
’s clone
will not throw an exception, due to its use of try
/catch
blocks; so, its client can call it without try
/catch
blocksName
’s clone
finally copies the data fields first
and last
and then returns the cloned objectWe 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
clone
method. Classes of immutable objects, for example, do not need aclone
method. The standard classString
is 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
clone
methodYour class must:
- Implement the
Cloneable
interface- 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.