This post will discuss various methods to copy objects in Java. Copying an object is creating a copy of an existing object in order to modify or move the copied object without impacting the original object.

Unlike C++, Java objects are not passed by value, but their references are passed by value instead. Consider the following code snippets,

Object ob1 = new Object();
Object ob2 = ob1;

 
Both ob1 and ob2 points to the same object now as this is just a reference to the original data; no copying occurs here.

Object ob = new Object();
fun(ob);

 
This is also just a reference to the original data as methods in Java are always pass by value. However, it is the value of the reference variable that is being passed.

int a = 5;
int b = a;

Since the data is primitive here, it simply copies the value of the primitive type.

 
Sometimes it is essential to create a copy of an object to use in the application. This post will discuss several ways to achieve that. Before we begin, let’s talk about shallow copy and deep copy of objects.

1.Shallow copy (field-by-field copy)

One method of copying an object is the shallow copy in which we allocate a new, uninitialized object and copy all fields (attributes) from the original object in it. This does not always result in desired behavior when the field value is a reference to an object, as it copies the reference, hence referring to the same object as an original object does. The referenced objects are thus shared, so if one object is modified, the change is visible in the other.

Copy objects – Shallow Copy

2. Deep copy

An alternative to shallow copy is a deep copy, where new objects are created for any referenced objects rather than references to objects being copied. A deep copy is a preferable approach over a shallow copy.

Copy objects – Deep Copy

 
There are several approaches to copy an object, as discussed below:

1. Using Copy Constructor or Factory

With the help of Copy Constructor, we can define the actions performed by the compiler when copying a class object. Any copy constructor implementation should perform deep copy for any referenced objects in the class by creating new objects and copy the values for the primitive and immutable types. It usually accepts only one parameter that is just another instance of the same class.

We can also use the static copy factory method to essentially do the same thing as the copy constructor method. Both approaches are shown below:

Download  Run Code

Output:

Calling Copy Constructor: Clone is [Jon Snow, 22, [Maths, English, Science]]
Deep Copy

Calling Copy Factory: Clone is [Jon Snow, 22, [Maths, English, Science]]
Deep Copy

2. Using clone() method

⮚ Using Object.clone() method

If the concrete type of the object to be cloned is known in advance, we can use the Object.clone() method, which creates and returns a copy of the object. The prototype of the Object.clone() is

protected Object clone() throws CloneNotSupportedException

All classes involved must implement the Cloneable interface, otherwise CloneNotSupportedException will be thrown. The default implementation Object.clone() is shown below:

 
This method returns a shallow copy of the Student object. In shallow copy, if the field 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, new objects are created for any referenced objects, unlike shallow copy where referenced objects are shared. For deep cloning, the clone() method must modify mutable non-final fields of the object returned by super.clone() before returning to the caller, as shown below:

 
This approach is discussed here in detail.

⮚ Using Apache SerializationUtils’s clone() method

Apache Commons Lang SerializationUtils also provides an implementation of the clone() method that performs deep cloning using serialization. It is very helpful as deep cloning using Object‘s clone method is time-consuming and error-prone for complex objects. It can be called as:

Student clone = (Student) SerializationUtils.clone(student);

3. Using Serialization

Serialization is the process of converting an object into a sequence of bytes and rebuilding those bytes later into a new object.

As seen before, deep copy using Object.clone() is very tedious to implement, error-prone, and difficult to maintain. Also, the Object.clone() method will not work if we assign a value to a final field. We can use Serialization to address these issues.

⮚ Using Serializable Interface

Java provides automatic serialization, which requires that the object be marked by implementing the java.io.Serializable interface. Implementing the interface marks the class as “okay to serialize”, and Java then handles serialization internally. Serialization won’t work on transient fields.

There are no serialization methods defined on the Serializable interface, but we can use ObjectOutputStream.writeObject() method to convert the object into a serialized form, and a corresponding ObjectInputStream.readObject() method to recreate an object from that representation. The result will be a completely distinct object, with completely distinct referenced objects.

Java Code for Serialization:

 
Java Code for Deserialization:

⮚ Using Apache commons SerializationUtils

We can also use the SerializationUtils class provided by Apache Commons Lang to assist with the serialization process. It provides serialize() and deserialize() methods to serialize and deserialize an object, respectively. Code is shown below:

4. Converting to JSON

It is widespread to receive JSON response from a Java web service instead of XML. Java doesn’t have any built-in support to create and process JSON data, but several good open-source libraries such as Google’s Gson, Jackson, and JSON-simple.

⮚ Using Google’s GSON Library

We can use Google’s GSON library (which uses reflection) to serialize a Java object to JSON string and then deserialize it to get a new object. This will perform a deep copy with a few restrictions. We know that a transient keyword indicates that a field should not be serialized. So this method will not copy transient fields. Also, this will not work on objects with recursive references.

Gson does not require additional modifications to classes of serialized/deserialized objects. Gson documentation states that the class to have defined default no-args constructor or have registered InstanceCreator.

The following code will produce a deep copy of the Student object by:

  1. Get an instance of Gson Object.
  2. Use gson.toJson() to serialize Object (convert Student Object to JSON string).
  3. Then use gson.fromJson() to unserialize Object (convert JSON string back to Student Object).

⮚ Using Jackson library

Another simple approach is to use the Jackson library to serialize complex Java Object to JSON and deserialize it back. It requires the class to have a default no-args constructor to instantiate Java Object from JSON string and only works on Java SE 1.5 or more. Unlike Gson, Jackson will require getters for all private fields, otherwise serialization and deserialization won’t work.

The following steps will produce a deep copy of the Student object by:

  1. Get an instance of ObjectMapper Object.
  2. Use mapper.writeValueAsString() to serialize Object (convert Student Object to JSON string).
  3. Then use mapper.readValue() to unserialize Object (convert JSON string back to Student Object).

 
Please note that both these methods have relatively poor performance than the copy constructor or Object.clone() method discussed above.

That’s all about copying objects in Java.

 
References:

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