Copy Objects in Java

In this post, we 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++, objects are not passed by value in Java but their references are passed by value instead. Consider below 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 a primitive here, it simply copies the value of the primitive type.

 


 

Sometimes it is very important to create a copy of an object, to use in application. In this post, we will cover 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 original object does. The referenced objects are thus shared, so if one of either objects 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. Deep copy is preferable approach over shallow copy.

Copy Objects - Deep Copy

 


 

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

1. Copy Constructor or Factory

With the help of Copy Constructor, we can define the actions to 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 type. It usually accepts only one parameter that is just another instance of the same class.

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

Java

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. clone() Method

 

2.1. Object’s Clone method()

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

protected Object clone() throws CloneNotSupportedException

All class involved must implement the Cloneable interface, else 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 the its value else 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, clone() method must modify mutable non-final fields of object returned by super.clone() before returning to the caller as shown below:

 

 
This approach is discussed here in detail.

 

2.2. Apache SerializationUtils’s clone() method

Apache Commons Lang SerializationUtils also provides implementation of 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. 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, Object.clone() method will not work if we try assign a value to a final field. We can use Serialization to address these issues.

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 –
 

 

Apache commons SerializationUtils

We can also use 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’s very common to receive JSON response from a Java web service instead of XML. Java doesn’t have any inbuilt support to create and process JSON data but there are several good open source libraries such as Google’s Gson, Jackson and JSON-simple.

 

1. 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 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.

Following code will produce a deep copy of 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).
     

 

2. Jackson library

Another simple approach is to use Jackson library to serialize complex Java Object to JSON and deserialize it back. It requires the class to have 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, else serialization and deserialization won’t work.

Following steps will produce a deep copy of 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 method have relatively poor performance than copy constructor or Object.clone() method discussed above.

 
References:

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

 
Thanks for reading.




Please use ideone or C++ Shell or any other online compiler link to post code in comments.
Like us? Please spread the word and help us grow. Happy coding 🙂
 





Leave a Reply

Notify of
avatar
wpDiscuz