DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Writing DTOs With Java8, Lombok, and Java14+
  • Redefining Java Object Equality
  • Addressing Memory Issues and Optimizing Code for Efficiency: Glide Case
  • Singleton: 6 Ways To Write and Use in Java Programming

Trending

  • Automatic Code Transformation With OpenRewrite
  • Automating Data Pipelines: Generating PySpark and SQL Jobs With LLMs in Cloudera
  • The Human Side of Logs: What Unstructured Data Is Trying to Tell You
  • Testing SingleStore's MCP Server
  1. DZone
  2. Coding
  3. Languages
  4. Java Cloning: Copy Constructors vs. Cloning

Java Cloning: Copy Constructors vs. Cloning

Let's run through the pros and cons of Object.clone() and see how it stacks up against copy constructors when it comes to copying objects.

By 
Naresh Joshi user avatar
Naresh Joshi
DZone Core CORE ·
Updated Aug. 20, 19 · Tutorial
Likes (21)
Comment
Save
Tweet
Share
230.6K Views

Join the DZone community and get the full member experience.

Join For Free

In my previous article, Shallow and Deep Java Cloning, I discussed Java cloning in detail and answered questions about how we can use cloning to copy objects in Java, the two different types of cloning (Shallow and Deep), and how we can implement both of them. If you haven’t read it, please go ahead.

In order to implement cloning, we need to configure our classes and to follow the following steps:

  • Implement the Cloneable interface in our class or its superclass or interface.
  • Define a clone() method that should handle CloneNotSupportedException (either throw or log).
  • And, in most cases from our clone() method, we call the clone() method of the superclass.
Java Cloning versus Copy Constructor

And super.clone() will call it's super.clone() and the chain will continue until the call reaches the clone() method of the Object class, which will create a field by field mem copy of our object and return it back.

Like everything, Cloning also comes with its advantages and disadvantages. However, Java cloning is more famous for its design issues but still, it is the most common and popular cloning strategy present today.

Advantages of Object.clone()

Object.clone(), as mentioned, has many design issues, but it is still the most popular and easiest way of copying objects. Some advantages of using clone() are:

  • Cloning requires much fewer lines of code — just an abstract class with a 4- or 5-line long clone() method, but we will need to override it if we need deep cloning.
  • It is the easiest way of copying objects, especially if we are applying it to an already developed or an old project. We just need to define a parent class, implement Cloneable in it, provide the definition of the clone() method, and we are ready. Every child of our parent will get the cloning feature. 
  • We should use clone to copy arrays because that’s generally the fastest way to do it.
  • As of release 1.5, calling clone on an array returns an array whose compile-timetype is the same as that of the array being cloned, which clearly means calling a clone on arrays does not require type-casting.

Disadvantages of Object.clone()

Below are some cons that cause many developers not to use Object.clone():

  • Using the Object.clone() method requires us to add lots of syntax to our code, like implementing a Cloneable interface, defining the clone() method and handling CloneNotSupportedException, and finally, calling Object.clone() and casting it on our object.
  • The Cloneable interface lacks the clone() method. Actually, Cloneable is a marker interface and doesn’t have any methods in it, and we still need to implement it just to tell the JVM that we can perform clone() on our object.
  • Object.clone() is protected, so we have to provide our own clone() and indirectly call Object.clone() from it.
  • We don’t have any control over object construction because Object.clone() doesn’t invoke any constructor.
  • If we are writing a clone method in a child class, e.g. Person, then all of its superclasses should define the clone() method in them or inherit it from another parent class. Otherwise, the super.clone() chain will fail.
  • Object.clone() supports only shallow copying, so the reference fields of our newly cloned object will still hold objects whose fields of our original object was holding. In order to overcome this, we need to implement clone() in every class whose reference our class is holding and then call their clone separately in our clone() method like in the example below.
  • We can not manipulate final fields in Object.clone() because final fields can only be changed through constructors. In our case, if we want every Person object to be unique by id, we will get the duplicate object if we use Object.clone() because Object.clone() will not call the constructor, and final id field can’t be modified from Person.clone().
class City implements Cloneable {
    private final int id;
    private String name;
    public City clone() throws CloneNotSupportedException {
    return (City) super.clone();
    }
}

class Person implements Cloneable {
    public Person clone() throws CloneNotSupportedException {
        Person clonedObj = (Person) super.clone();
        clonedObj.name = new String(this.name);
        clonedObj.city = this.city.clone();
        return clonedObj;
    }
}


Because of the above design issues with Object.clone(), developers always prefer other ways to copy objects like using:

  •  BeanUtils.cloneBean(object): creates a shallow clone similar to Object.clone().
  •  SerializationUtils.clone(object): creates a deep clone. (i.e. the whole properties graph is cloned, not only the first level), but all classes must implement Serializable.
  •  Java Deep Cloning Library: offers deep cloning without the need to implement Serializable.

All these options require the use of some external library, plus these libraries will also be using Serialization or Copy Constructors or Reflection internally to copy our object. So if you don’t want to go with the above options or want to write your own code to copy the object, then you can use:

  1.  Serialization 
  2.  Copy constructors 

Serialization

As discussed in 5 different ways to create objects in Java, deserialising a serialised object creates a new object with the same state as in the serialized object. So similar to above cloning approaches we can achieve deep cloning functionality using object serialization and deserialization as well and with this approach we do not have worry about or write code for deep cloning, we get it by default.

We can do it like it is done below or we can also use other APIs like JAXB which supports serialization.

// Method to deep clone an object using in memory serialization.
public Employee copy(Person original) throws IOException, ClassNotFoundException {
    // First serializing the object and its state to memory using ByteArrayOutputStream instead of FileOutputStream.
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream out = new ObjectOutputStream(bos);
    out.writeObject(original);

    // And then deserializing it from memory using ByteArrayOutputStream instead of FileInputStream,
    // Deserialization process will create a new object with the same state as in the serialized object.
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream in = new ObjectInputStream(bis);
    return (Person) in.readObject();
}


However, cloning an object using serialization comes with some performance overhead and we can improve on it by using in-memory serialization if we just need to clone the object and don’t need to persist it in a file for future use, you can read more on How To Deep Clone An Object Using Java In Memory Serialization.


Copy Constructors

This method of copying objects is the most popular among the developer community. It overcomes every design issue of Object.clone() and provides better control over object construction.

public Person(Person original) {
    this.id = original.id + 1;
    this.name = new String(original.name);
    this.city = new City(original.city);
}


Advantages of Copy Constructors Over Object.clone()

Copy constructors are better than Object.clone() because they:

  • Don’t force us to implement any interface or throw an exception, but we can surely do it if it is required.
  • Don’t require any type casting.
  • Don’t require us to depend on an unknown object creation mechanism.
  • Don’t require parent classes to follow any contract or implement anything.
  • Allow us to modify final fields.
  • Allow us to have complete control over object creation, meaning we can write our initialization logic in it.

By using the copy constructors strategy, we can also create conversion constructors, which can allow us to convert one object to another object — e.g. The ArrayList(Collection<? extends E> c) constructor generates an ArrayList from any Collection object and copies all items from the Collection object to a newly created ArrayList object.

Cloning Java (programming language) Object (computer science)

Published at DZone with permission of Naresh Joshi, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Writing DTOs With Java8, Lombok, and Java14+
  • Redefining Java Object Equality
  • Addressing Memory Issues and Optimizing Code for Efficiency: Glide Case
  • Singleton: 6 Ways To Write and Use in Java Programming

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!