Trusted answers to developer questions

How to define the method clone in your Java class

Get Started With Machine Learning

Learn the fundamentals of Machine Learning with this free course. Future-proof your career by adding ML skills to your toolkit — or prepare to land a job in AI or Data Science.

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:

NameDemo.java
Name.java
public class NameDemo
{
public static void main(String[] args)
{
// Create a Name object
Name aName = new Name();
aName.setName("Jamie", "Java");
System.out.println("Object A's name is " + aName); // Calls toString
// Clone the object
Name theClone = (Name)aName.clone(); // Note the cast
System.out.println("The clone's name is " + theClone + "\n");
// Change aName's name; see whether it changes the clone
aName.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 name
theClone.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 Cloneable clause
  • Name’s public method clone overrides Object’s protected clone method
  • Both versions of clone 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
  • Because 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 blocks
  • Name’s clone finally copies the data fields first and last and 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 immutablecannot be changed, you will see no difference in the way that clone copies them.

✏️ Note

Not all classes should have a public clone method. Classes of immutable objects, for example, do not need a clone method. The standard class String is such a class; it does not have a public method clone.

! 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:

PersonDemo.java
Name.java
Person.java
/** Name.java by F. M. Carrano
A class of names, each containing a first name and a last name.
*/
public class Name implements Cloneable
{
private String first; // First name
private String last; // Last name
/** Creates a default name whose first and last names are empty strings. */
public Name()
{
first = "";
last = "";
} // End default constructor
public 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 copy
theCopy.first = first;
theCopy.last = last;
/*
// Deep copy
theCopy.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 method

Your class must:

  • Implement the Cloneable interface
  • Define a public method (clone) that overrides Object’s protected version

✏️ Note

If your class’s superclass defines its own public method (clone), your class can override it instead of overriding Object’s protected method.

RELATED TAGS

java
Did you find this helpful?