This post will discuss how to copy an object in Java using the clone() method in Object class and one provided by Apache Commons Lang. We will also discuss shallow copy and deep copy in detail.

Cloning an object creates a copy of an existing object to modify or move the copied object without impacting the original object. In Java, objects are manipulated through reference variables, and there is no operator for actually copying an object. Remember that the assignment operator duplicates the reference, not the object.

1. Using Object.clone() method

Classes that want copying functionality can use Object.clone() method, which creates and returns a copy of the object. The prototype of the Object.clone() is

As the return type of Object.clone() is Object, typecasting is needed to assign the returned Object reference to a reference to an object.

All classes involved must implement the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class. Invoking Object’s clone method on an instance that does not implement the Cloneable interface results in the CloneNotSupportedException.

Since every class implicitly extends Object class, Object.clone() is an overridable method. Since Java provides support for covariant return types, the return type of clone() can be changed from Object to the type of the object being cloned, and clone() should override the protected Object.clone() method with a public method.

The clone() behaves similarly as a Copy Constructor. It calls the clone() method of its parent class to obtain the copy, etc., until it eventually reaches Object’s clone() method, which creates a new instance of the same class as the object copies all the fields to the new instance.

Cons:

1. Object.clone() will not work on interfaces and abstract classes.

The only way to use the Object.clone() method is if the class of an object is known, i.e., we cannot access the clone() method on an abstract type since most interfaces and abstract classes in Java do not specify a public clone() method.

For instance, one cannot invoke clone() on a map reference in Java because map specifies no public clone() method. Only map implementations like HashMap and LinkedHashMap have clone() methods, but to carry around the class type of object is not recommended, and it is contrary to the “Program to Interface, not Implementation” principle.

 
2. The default implementation Object.clone() method returns a Shallow Copy.

In shallow copy, if the field value is a primitive type, it copies its value; otherwise, if the field value is a reference to an object, it copies the reference, hence referring to the same object. Now, if one of these objects is modified, the change is visible in the other. In Deep Copy, in contrast to the shallow copy, the referenced objects are not shared; instead, new objects are created for any referenced objects.

Shallow Cloning

Shallow Copy

 
The following program demonstrates using the Object.clone() method by using its default implementation, which returns a shallow copy. We will cover deep copy using the clone() method in the next section.

Download  Run Code

Output:

Cloned Object: [Jon Snow, 22, [Maths, English, Science, History]]
 
Shallow Copy
Shallow Copy
{Jon Snow=22, John Cena=40}

Deep Cloning

If a class contains only primitives and Immutable fields, a shallow copy works fine. But any mutable fields such as collections and arrays would be shared between the original and the copy since Object.clone() returns an exact copy of the original object.

For deep cloning, if a class contains any object references, then the clone() method should perform any required modifications on the object received from the superclass before returning to the caller. i.e., clone() method must modify mutable fields of objects returned by super.clone(). One way of doing it is to call the clone() method on mutable fields.

Deep Copy

If we try to assign values to final fields within a clone() method, it will result in a compilation error. The field’s value is an immutable object, we can just let it copy the reference, and both the original and its clone will share the same object. But for mutable objects, it must be deeply copied.

Serialization and deserialization is another alternative to using a clone which handles final data members correctly, as shown in the next section. We can also make use of Copy Constructor that takes an instance of the same class as the object and copies all the primitive fields, and create new objects for any referenced objects to that new instance.

Download  Run Code

Output:

Cloned Object: [Jon Snow, 22, [Maths, English, Science, History]]
 
Deep Copy
Deep Copy
{Jon Snow=22}

 
The Custom clone() method is tedious to implement, error-prone, and difficult to maintain. The code must be modified every time any change is made to the class fields.

2. Deep Cloning: Apache SerializationUtils.clone() method

The JDK provides no deep-copy equivalent to Object.clone() method. But we can refer implementation of clone() method provided by Apache Commons Lang SerializationUtils class. The prototype of the SerializationUtils.clone() is:

It basically performs deep cloning using serialization. It is beneficial as deep cloning using the Object’s clone method is very painful and error-prone for complex object graphs.

Cons:

  • This is many times slower than manually cloning on all objects in your object instance.
  • If this method is used, all the objects involved must be Serializable, i.e., objects must implement Serializable interface; otherwise, it will throw a java.io.NotSerializableException.

The following program demonstrates it:

Download Code

Output:

Cloned Object: [Jon Snow, 22, [Jon Snow, 22]]
 
Deep Copy
Deep Copy
{Jon Snow=22}

That’s all about the clone() method in Java.

 
References:

https://en.wikipedia.org/wiki/Object_copying#Copying_in_Java
https://en.wikipedia.org/wiki/Clone_(Java_method)