Copy an object in Java

I have an object that I need to copy in Java. I need to create a copy and run some tests on it without changing the original object itself.

I assumed that I needed to use the clone() method, but this is protected. Having done some research on the net, I can see that this can be overriden with a public method in my class. But I cannot find an explanation on how to do this. How could this be done?

Also, is this the best way of achieving what I need?

Answers


Another option by using Copy Constructor (from Java Practices):

public final class Galaxy {

    public Galaxy (double aMass, String aName) {
        fMass = aMass;
        fName = aName;
    }

    /**
    * Copy constructor.
    */
    public Galaxy(Galaxy aGalaxy) {
        this(aGalaxy.getMass(), aGalaxy.getName());
        //no defensive copies are created here, since 
        //there are no mutable object fields (String is immutable)
    }

    /**
    * Alternative style for a copy constructor, using a static newInstance
    * method.
    */
    public static Galaxy newInstance(Galaxy aGalaxy) {
        return new Galaxy(aGalaxy.getMass(), aGalaxy.getName());
    }

    public double getMass() {
        return fMass;
    }

    /**
    * This is the only method which changes the state of a Galaxy
    * object. If this method were removed, then a copy constructor
    * would not be provided either, since immutable objects do not
    * need a copy constructor.
    */
    public void setMass( double aMass ){
        fMass = aMass;
    }

    public String getName() {
        return fName;
    }

    // PRIVATE /////
    private double fMass;
    private final String fName;

    /**
    * Test harness.
    */
    public static void main (String... aArguments){
        Galaxy m101 = new Galaxy(15.0, "M101");

        Galaxy m101CopyOne = new Galaxy(m101);
        m101CopyOne.setMass(25.0);
        System.out.println("M101 mass: " + m101.getMass());
        System.out.println("M101Copy mass: " + m101CopyOne.getMass());

        Galaxy m101CopyTwo = Galaxy.newInstance(m101);
        m101CopyTwo.setMass(35.0);
        System.out.println("M101 mass: " + m101.getMass());
        System.out.println("M101CopyTwo mass: " + m101CopyTwo.getMass());
    }
} 

There are two popular approaches. One is to provide a clone method as you mentioned, like so.

public class C implements Cloneable {
    @Override public C clone() {
        try {
            final C result = (C) super.clone();
            // copy fields that need to be copied here!
            return result;
        } catch (final CloneNotSupportedException ex) {
            throw new AssertionError();
        }
}

Pay attention to the "copy fields ... here!" part. The initial result is only a shallow copy, meaning that if there's a reference to an object, both the original and result will share the same object. For example, if C contains private int[] data you'd probably want to copy that.

...
final C result = (C) super.clone();
result.data = data.clone();
return result;
...

Note that you don't need to copy primitive fields, as their content is already copied, or immutable objects, as they can't change anyways.

The second approach is to provide a copy constructor.

public class C {
    public C(final C c) {
        // initialize this with c
    }
}

Or a copy factory.

public class C {
    public static C newInstance(final C c) {
        return new C(c);
    }

    private C(final C c) {
        // initialize this with c
    }
}

Both approaches have their respective properties. clone is nice because its a method, so you don't have to know the exact type. In the end, you should always end up with a "perfect" copy. The copy constructor is nice because the caller has a chance to decide, as can be seen by the Java Collections.

final List c = ... 
// Got c from somewhere else, could be anything.
// Maybe too slow for what we're trying to do?

final List myC = new ArrayList(c);
// myC is an ArrayList, with known properties

I recommend choosing either approach, whichever suits you better.

I'd use the other approaches, like reflective copying or immediate serializing/deserializing, in unit tests only. To me, they feel less appropriate for production code, mainly because of performance concerns.


Some options:

  • You can implement Cloneable for your object and put clone() method as public. See full explanation here: http://www.cafeaulait.org/course/week4/46.html However, this produces a shallow copy and might be not something you want.
  • You can serialize and deserialize your object. You will need to implement Serializable interface for the object and all its fields.
  • You can use XStream to perform serialization via XML - you won't have to implement anything here.

For test code Serialization is maybe the safest answer, especially if the object is already Serializable try Apache Commons SerializationUtils for an implementation.


You can use org.apache.commons.lang3.SerializationUtils class for object cloning, - Class should implement Serializable interface.

  • ClassName copyobject = SerializationUtils.clone(classobjectTocopy)

SerializationUtils.clone is also supported on Google App Engine instance


Joshua Bloch has some interesting things to say about cloneable. Depending on the size/construction of the object, I'd add a copy constructor to the object, or serialise/deserialise using one of the solutions mentioned above.


There are multiple ways to copy object in java(shallow or deep). This Answer will help you.


Need Your Help

How can i add microsoftOfficeWebComponents owc To Access 2013

vba ms-access access-vba ms-access-2013

I have a machine in office 2013, I installed microsoft office web Components owc 11.0 , but it does not appear in the list of reference vba

How to get fixed cell value, not formula?

google-apps-script google-sheets

I have a cell in Google Sheets, with =NOW() formula in it. All I need - to get the value, generated by formula (22.01.2014 15:23:51), not the formula by itself.