914

Consider the code below:

DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'

DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'

dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'

So, I want to copy the dum to dumtwo and change dum without affecting the dumtwo. But the code above is not doing that. When I change something in dum, the same change is happening in dumtwo also.

I guess, when I say dumtwo = dum, Java copies the reference only. So, is there any way to create a fresh copy of dum and assign it to dumtwo?

Mooncrater
  • 4,146
  • 4
  • 33
  • 62
Veera
  • 32,532
  • 36
  • 98
  • 137

23 Answers23

696

Create a copy constructor:

class DummyBean {
  private String dummy;

  public DummyBean(DummyBean another) {
    this.dummy = another.dummy; // you can access  
  }
}

Every object has also a clone method which can be used to copy the object, but don't use it. It's way too easy to create a class and do improper clone method. If you are going to do that, read at least what Joshua Bloch has to say about it in Effective Java.

Bob Cross
  • 22,116
  • 12
  • 58
  • 95
egaga
  • 21,042
  • 10
  • 46
  • 60
  • 46
    But then he'd have to change his code to DummyBean two = new DummyBean(one); Right? – Chris K May 17 '10 at 17:43
  • 13
    Does this method effectively accomplish the same thing as a deep copy? – Matthew Piziak Jul 13 '11 at 18:46
  • 137
    @MatthewPiziak, to me - this would not be a deep clone since any nested objects would still be referencing the original source instance, not a duplicate unless each reference (non-value type) object supplies the same constructor template as above. – SliverNinja - MSFT Nov 20 '11 at 11:33
  • 4
    Can someone confirm if this really works? It looks like it will create another DummyBeam instance, but both dummy's will still refer to the same String... – Timmmm Jan 27 '12 at 13:22
  • 18
    @Timmmm: Yes, they will reference the same String but because it is immutable, it is ok. Same goes for primitives. For non-primitives, you would just do copy contructor call recursively. e.g. If DummyBean referenced FooBar then FooBar should have contructor FooBar(FooBar another), and dummy should call this.foobar = new FooBar(another.foobar) – egaga Feb 03 '12 at 18:02
  • 2
    If you do: DummyBean two = new DummyBean(one); one.setDummy("johndoe"); then two.getDummy() will be "johndoe", so this is not a correct answer. – Christian Vielma Jun 27 '12 at 19:38
  • 7
    @ChristianVielma: No, it won't be "johndoe". Like Timmmm said, the string itself is immutable. With one, setDummy(..) you set the reference in one to point to "johndoe", but not the one in one. – keuleJ Jun 28 '12 at 16:26
  • 3
    This solution does not work on abstract base classes, which makes it pretty useless in many OOP design patterns. – Max Jan 24 '14 at 22:52
  • 1
    With all Eclipse code generation features, I am surprised there isn't one to create the constructor. I sometimes have configuration classes with a lot of fields and it sure would help if Eclipse could generate that copy constructor automatically. – Lolo Apr 24 '14 at 16:17
  • 1
    This is a very limited solution, because it only works when there are no subclasses. That is, if you know at compile time what class the object has. – fishinear Nov 21 '16 at 17:01
  • 3
    I really don't like the `copy constructor` since this is not clear that a constructor would copy an instance instead of simply take some values or using his reference. I prefer to use a clone method that is more comprehensive. With `DummyBean DummyBean.clone()`, you can tell easily the output but the constructor is vague. – AxelH Dec 30 '16 at 08:46
  • It could be good to narrow the description as "Every object has also a protected clone method which can be used to copy the object by implementing Cloneable interface". – thread-game Apr 07 '17 at 06:45
  • 2
    if you have 100 fields, this is hard to do. – ACV Jun 27 '17 at 16:24
  • 1
    How to copy all properties of a class at once rather than doing the assignment one by one. Because you see i have a class with around 50 properties, and there is a high chance that i might miss assignment of some of them. Any way out ? – zulkarnain shah Jul 10 '17 at 12:11
  • What about classes that have already been defined and can't be changed? – Pika Supports Ukraine Oct 19 '18 at 03:44
  • How to create it automatically? – Alex78191 Mar 03 '19 at 18:52
452

Basic: Object Copying in Java.

Let us Assume an object- obj1, that contains two objects, containedObj1 and containedObj2.
enter image description here

shallow copying:
shallow copying creates a new instance of the same class and copies all the fields to the new instance and returns it. Object class provides a clone method and provides support for the shallow copying.
enter image description here

Deep copying:
A deep copy occurs when an object is copied along with the objects to which it refers. Below image shows obj1 after a deep copy has been performed on it. Not only has obj1 been copied, but the objects contained within it have been copied as well. We can use Java Object Serialization to make a deep copy. Unfortunately, this approach has some problems too(detailed examples).
enter image description here

Possible Problems:
clone is tricky to implement correctly.
It's better to use Defensive copying, copy constructors(as @egaga reply) or static factory methods.

  1. If you have an object, that you know has a public clone() method, but you don’t know the type of the object at compile time, then you have problem. Java has an interface called Cloneable. In practice, we should implement this interface if we want to make an object Cloneable. Object.clone is protected, so we must override it with a public method in order for it to be accessible.
  2. Another problem arises when we try deep copying of a complex object. Assume that the clone() method of all member object variables also does deep copy, this is too risky of an assumption. You must control the code in all classes.

For example org.apache.commons.lang.SerializationUtils will have method for Deep clone using serialization(Source). If we need to clone Bean then there are couple of utility methods in org.apache.commons.beanutils (Source).

  • cloneBean will Clone a bean based on the available property getters and setters, even if the bean class itself does not implement Cloneable.
  • copyProperties will Copy property values from the origin bean to the destination bean for all cases where the property names are the same.
Chandra Sekhar
  • 16,256
  • 10
  • 67
  • 90
  • 1
    Can you please explain what is object contained within another? – Freakyuser Jun 13 '13 at 06:49
  • 1
    @Chandra Sekhar "shallow copying creates a new instance of the same class and copies all the fields to the new instance and returns it" that's wrong to mention all the fields,bcz objects don't get copied only the references get copied which points to the same object that old one(original) was pointing to. – JAVA Oct 29 '13 at 11:49
  • 4
    @sunny - Chandra's description is correct. And so is your description of what happens; I am saying that you have an incorrect understanding of the meaning of "copies all the fields". The field **is** the reference, it is not the object being referred to. "copying all fields" **means** "copying all those references". It is good that you pointed out what exactly this means, for anyone else who has the same mis-interpretation as you, of the statement "copying all fields". :) – ToolmakerSteve Aug 25 '14 at 22:41
  • 2
    ... if we think in terms of some lower-level OO language, with "pointers" to objects, such a field would contain the address in memory (such as "0x70FF1234") at which the object data is found. That address is the "field value" that is being copied (assigned). You are correct that the end result is that both objects have fields that refer to (point at) the same object. – ToolmakerSteve Aug 25 '14 at 22:47
  • https://www.baeldung.com/java-deep-copy – Smart Coder Oct 27 '22 at 19:48
162

In the package import org.apache.commons.lang.SerializationUtils; there is a method:

SerializationUtils.clone(Object);

Example:

this.myObjectCloned = SerializationUtils.clone(this.object);
Salvatorelab
  • 11,614
  • 6
  • 53
  • 80
pacheco
  • 1,637
  • 1
  • 10
  • 2
113

Just follow as below:

public class Deletable implements Cloneable{

    private String str;
    public Deletable(){
    }
    public void setStr(String str){
        this.str = str;
    }
    public void display(){
        System.out.println("The String is "+str);
    }
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

and wherever you want to get another object, simple perform cloning. e.g:

Deletable del = new Deletable();
Deletable delTemp = (Deletable ) del.clone(); // this line will return you an independent
                                 // object, the changes made to this object will
                                 // not be reflected to other object
Bhasker Tiwari
  • 1,139
  • 1
  • 7
  • 2
  • 2
    Did you test this? I could use this for my project and it is important to be correct. – misty Aug 24 '16 at 21:37
  • 3
    @misty I've tested it. Works perfectly on my production app – Andrii Kovalchuk Sep 27 '16 at 11:37
  • 1
    After cloning, when you modify the original object, it is modifying the clone as well. – Sibish Aug 30 '17 at 23:58
  • I also have the same problem, when I change the properties of the original object then the values are changed in the cloned object. – jmoran Oct 06 '17 at 19:18
  • 11
    This is wrong in that it is *not* a deep copy which was asked for. – Bluehorn Nov 06 '17 at 12:10
  • 2
    This method clone the pointer which points for the cloneable object, but all the properties inside both objects are the same, So there is a new object created in the memory, but the data inside each object is the same data from memory – Omar HossamEldin Feb 14 '18 at 12:49
  • To Bhasker Tiwari's defense however, the example given concerns a `String` reference only, which is perfectly safe (and infact preferred) to share among copies. Admittedly it should have been made clear that this is a special case and that further action needs to be taken when deep cloning objects with references to mutable objects. – aioobe May 01 '18 at 12:51
47

Why is there no answer for using Reflection API?

private static Object cloneObject(Object obj){
        try{
            Object clone = obj.getClass().newInstance();
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                field.set(clone, field.get(obj));
            }
            return clone;
        }catch(Exception e){
            return null;
        }
    }

It's really simple.

EDIT: Include child object via recursion

private static Object cloneObject(Object obj){
        try{
            Object clone = obj.getClass().newInstance();
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                if(field.get(obj) == null || Modifier.isFinal(field.getModifiers())){
                    continue;
                }
                if(field.getType().isPrimitive() || field.getType().equals(String.class)
                        || field.getType().getSuperclass().equals(Number.class)
                        || field.getType().equals(Boolean.class)){
                    field.set(clone, field.get(obj));
                }else{
                    Object childObj = field.get(obj);
                    if(childObj == obj){
                        field.set(clone, clone);
                    }else{
                        field.set(clone, cloneObject(field.get(obj)));
                    }
                }
            }
            return clone;
        }catch(Exception e){
            return null;
        }
    }
WillingLearner
  • 739
  • 6
  • 10
  • This looks much better, but you only need to consider final fields as setAccessible(true) might fail, so maybe u need to separately handle the exception IllegalAccessException thrown when calling field.set(clone, field.get(obj)) separately. – Max Aug 21 '14 at 09:12
  • 1
    I liked it so much but can you refactor it to use generics ? private static T cloneObject(T obj) { .... } – Adelin Feb 08 '16 at 14:52
  • 2
    I think it's issue when we have reference from properties to it parents: `Class A { B child; } Class B{ A parent; }` – nhthai Feb 16 '16 at 10:25
  • It fails even int this situation, need to be handled, i will play with it tomorow. `class car { car car = new car(); }` – Ján Яabčan Sep 16 '16 at 21:40
  • This is not cloning the property with their values. Always returning a cloned object with all properties set to null – Varshney P. Sep 23 '16 at 05:46
  • worked for me. i would change line `field.getType().getSuperclass().equals(Number.class)` to `(field.getType().getSuperclass() != null && field.getType().getSuperclass().equals(Number.class))` to avoid NPE when field type has no superclass – Dustin Dec 04 '16 at 21:05
  • I had some issues related to null values using getSuperClass, which can be solved using `Number.class.equals(field.getType().getSuperclass())` and with arrays it didn't worked, which can be fixed like this `if(Object[].class.isAssignableFrom(field.getType())){ Object[] values = ((Object[])field.get(obj)); Object[] valuesClone = Arrays.copyOf(values, values.length); field.set(clone, valuesClone); }` – EliuX Apr 13 '17 at 00:07
  • 3
    This is error prone. Not sure how will it handle collections – ACV Jun 27 '17 at 16:26
  • @WillingLearner, this creates a shallow copy, right? And what about fields inherited from super classes? I assume you would want to recurse on `getSuperClass()` to make sure these fields are copied too? – aioobe May 01 '18 at 12:55
34

I use Google's JSON library to serialize it then create a new instance of the serialized object. It does deep copy with a few restrictions:

  • there can't be any recursive references

  • it won't copy arrays of disparate types

  • arrays and lists should be typed or it won't find the class to instantiate

  • you may need to encapsulate strings in a class you declare yourself

I also use this class to save user preferences, windows and whatnot to be reloaded at runtime. It is very easy to use and effective.

import com.google.gson.*;

public class SerialUtils {

//___________________________________________________________________________________

public static String serializeObject(Object o) {
    Gson gson = new Gson();
    String serializedObject = gson.toJson(o);
    return serializedObject;
}
//___________________________________________________________________________________

public static Object unserializeObject(String s, Object o){
    Gson gson = new Gson();
    Object object = gson.fromJson(s, o.getClass());
    return object;
}
       //___________________________________________________________________________________
public static Object cloneObject(Object o){
    String s = serializeObject(o);
    Object object = unserializeObject(s,o);
    return object;
}
}
Peter
  • 854
  • 10
  • 19
  • 1
    This works great. But watch out if you try to clone something like List. It will be buggy, my Integers got turned into Doubles, 100.0. It took me a long while to understand why are they like that. The solution was to clone Integers them one by one and add to the list in a cycle. – paakjis Oct 25 '19 at 08:02
24

Yes, you are just making a reference to the object. You can clone the object if it implements Cloneable.

Check out this wiki article about copying objects.

Refer here: Object copying

soumya
  • 3,801
  • 9
  • 35
  • 69
Chrisb
  • 729
  • 1
  • 5
  • 11
18

Add Cloneable and below code to your class

public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

Use this clonedObject = (YourClass) yourClassObject.clone();

Teja Maridu
  • 515
  • 1
  • 6
  • 14
18

Deep Cloning is your answer, which requires implementing the Cloneable interface and overriding the clone() method.

public class DummyBean implements Cloneable {

   private String dummy;

   public void setDummy(String dummy) {
      this.dummy = dummy;
   }

   public String getDummy() {
      return dummy;
   }

   @Override
   public Object clone() throws CloneNotSupportedException {
      DummyBean cloned = (DummyBean)super.clone();
      cloned.setDummy(cloned.getDummy());
      // the above is applicable in case of primitive member types like String 
      // however, in case of non primitive types
      // cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
      return cloned;
   }
}

You will call it like this DummyBean dumtwo = dum.clone();

abbas
  • 6,453
  • 2
  • 40
  • 36
13

This works too. Assuming model

class UserAccount{
   public int id;
   public String name;
}

First add compile 'com.google.code.gson:gson:2.8.1' to your app>gradle & sync. Then

Gson gson = new Gson();
updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);

You can exclude using a field by using transient keyword after access modifier.

Note: This is bad practice. Also don't recommend to use Cloneable or JavaSerialization It's slow and broken. Write copy constructor for best performance ref.

Something like

class UserAccount{
        public int id;
        public String name;
        //empty constructor
        public UserAccount(){}
        //parameterize constructor
        public UserAccount(int id, String name) {
            this.id = id;
            this.name = name;
        }

        //copy constructor
        public UserAccount(UserAccount in){
            this(in.id,in.name);
        }
    }

Test stats of 90000 iteration:
Line UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class); takes 808ms

Line UserAccount clone = new UserAccount(aO); takes less than 1ms

Conclusion: Use gson if your boss is crazy and you prefer speed. Use second copy constructor if you prefer quality.

You can also use copy constructor code generator plugin in Android Studio.

Qamar
  • 4,959
  • 1
  • 30
  • 49
10

Use a deep cloning utility:

SomeObjectType copy = new Cloner().deepClone(someObject);

This will deep copy any java object, check it out at https://github.com/kostaskougios/cloning

Hatem Alimam
  • 9,968
  • 4
  • 44
  • 56
Cojones
  • 1,906
  • 22
  • 25
  • 1
    didn't work for me using a custom class. getting the following exception: java.lang.NoClassDefFoundError: sun.reflect.ReflectionFactory – stefanjunker Jun 13 '12 at 15:28
10

Here's a decent explanation of clone() if you end up needing it...

Here: clone (Java method)

soumya
  • 3,801
  • 9
  • 35
  • 69
Jon Bringhurst
  • 1,340
  • 1
  • 10
  • 21
8

Alternative to egaga's constructor method of copy. You probably already have a POJO, so just add another method copy() which returns a copy of the initialized object.

class DummyBean {
    private String dummyStr;
    private int dummyInt;

    public DummyBean(String dummyStr, int dummyInt) {
        this.dummyStr = dummyStr;
        this.dummyInt = dummyInt;
    }

    public DummyBean copy() {
        return new DummyBean(dummyStr, dummyInt);
    }

    //... Getters & Setters
}

If you already have a DummyBean and want a copy:

DummyBean bean1 = new DummyBean("peet", 2);
DummyBean bean2 = bean1.copy(); // <-- Create copy of bean1 

System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());

//Change bean1
bean1.setDummyStr("koos");
bean1.setDummyInt(88);

System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());

Output:

bean1: peet 2
bean2: peet 2

bean1: koos 88
bean2: peet 2

But both works well, it is ultimately up to you...

Pierre
  • 8,397
  • 4
  • 64
  • 80
7

Pass the object that you want to copy and get the object you want:

private Object copyObject(Object objSource) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(objSource);
            oos.flush();
            oos.close();
            bos.close();
            byte[] byteData = bos.toByteArray();
            ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
            try {
                objDest = new ObjectInputStream(bais).readObject();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return objDest;

    }

Now parse the objDest to desired object.

Happy Coding!

Nick
  • 138,499
  • 22
  • 57
  • 95
A-Droid Tech
  • 2,301
  • 24
  • 33
  • A good solution to have a solution. But if the purpose of cloning is to improve performance, this solution is not working because it has a heavy processesing – iman kazemayni Apr 23 '23 at 02:59
7

Use gson for duplicating an object.

public static <T>T copyObject(Object object){
    Gson gson = new Gson();
    JsonObject jsonObject = gson.toJsonTree(object).getAsJsonObject();
    return gson.fromJson(jsonObject,(Type) object.getClass());
}

Assume I have an object person.So

Person copyPerson = copyObject(person);

Note: The performance is much slower.

tuhin47
  • 5,172
  • 4
  • 19
  • 29
7

To do that you have to clone the object in some way. Although Java has a cloning mechanism, don't use it if you don't have to. Create a copy method that does the copy work for you, and then do:

dumtwo = dum.copy();

Here is some more advice on different techniques for accomplishing a copy.

Community
  • 1
  • 1
Yishai
  • 90,445
  • 31
  • 189
  • 263
6

Other than explicitly copying, another approach is to make the object immutable (no set or other mutator methods). In this way the question never arises. Immutability becomes more difficult with larger objects, but that other side of that is that it pushes you in the direction of splitting into coherent small objects and composites.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
4
class DB {
  private String dummy;

  public DB(DB one) {
    this.dummy = one.dummy; 
  }
}
Mahdi Abdi
  • 682
  • 6
  • 27
3
public class MyClass implements Cloneable {

private boolean myField= false;
// and other fields or objects

public MyClass (){}

@Override
public MyClass clone() throws CloneNotSupportedException {
   try
   {
       MyClass clonedMyClass = (MyClass)super.clone();
       // if you have custom object, then you need create a new one in here
       return clonedMyClass ;
   } catch (CloneNotSupportedException e) {
       e.printStackTrace();
       return new MyClass();
   }

  }
}

and in your code:

MyClass myClass = new MyClass();
// do some work with this object
MyClass clonedMyClass = myClass.clone();
The Unfun Cat
  • 29,987
  • 31
  • 114
  • 156
Amir Hossein Ghasemi
  • 20,623
  • 10
  • 57
  • 53
  • 3
    There is no point in set "throws CloneNotSupportedException" in the declaration if you try catch the exception and is not thrown up. So, you can just remove it. – Christian Jun 25 '18 at 11:08
3

You can deep copy automatically with XStream, from http://x-stream.github.io/:

XStream is a simple library to serialize objects to XML and back again.

Add it to your project (if using maven)

<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.3.1</version>                
</dependency>

Then

DummyBean dum = new DummyBean();
dum.setDummy("foo");
DummyBean dumCopy = (DummyBean) XSTREAM.fromXML(XSTREAM.toXML(dum));

With this you have a copy without the need to implement any cloning interface.

Jaime Hablutzel
  • 6,117
  • 5
  • 40
  • 57
1

If you can add an annotation to the source file, an annotation processor or code generator like this one can be used.

import net.zerobuilder.BeanBuilder

@BeanBuilder
public class DummyBean { 
  // bean stuff
}

A class DummyBeanBuilders will be generates, which has a static method dummyBeanUpdater to create shallow copies, the same way as you would do it manually.

DummyBean bean = new DummyBean();
// Call some setters ...
// Now make a copy
DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done();
Lars Bohl
  • 1,001
  • 16
  • 20
1

Using Kotlin extension function

fun <T : Any?> T.duplicate(): T? {
    var copyObject: T? = null
    try {
        val byteArrayOutputStream = ByteArrayOutputStream()
        val objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
        objectOutputStream.writeObject(this)
        objectOutputStream.flush()
        objectOutputStream.close()
        byteArrayOutputStream.close()
        val byteData = byteArrayOutputStream.toByteArray()
        val byteArrayInputStream = ByteArrayInputStream(byteData)
        try {
            copyObject = ObjectInputStream(byteArrayInputStream).readObject() as T
        } catch (e: ClassNotFoundException) {
            e.printStackTrace()
        }
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return copyObject
}

Use case

var object = Any()
var duplicateObject = object.duplicate()

Java

<T extends Object> T copyObject(T sourceObject) {

    T copyObject = null;

    try {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(sourceObject);
        objectOutputStream.flush();
        objectOutputStream.close();
        byteArrayOutputStream.close();
        byte[] byteData = byteArrayOutputStream.toByteArray();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteData);
        try {
            copyObject = (T) new ObjectInputStream(byteArrayInputStream).readObject();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return copyObject;
}

Use case

Object object = new Object();
Object duplicateObject = copyObject(object);

==============================================

Kotlin Update

If you use data class then you will have copy method that copies the Kotlin data class. Cool thing is you could also pass some values to modify the object with new copy. I would recommend this way.

Example:

//class

data class TestModel(val title: String, var subtitle: String)

Use case

val testClass = TestModel("Test title", "Test subtitle")

val newInstance = testClass.copy(subtitle = "new subtitle for copy instance")
Ngima Sherpa
  • 1,397
  • 1
  • 13
  • 34
1

You can try to implement Cloneable and use the clone() method; however, if you use the clone method you should - by standard - ALWAYS override Object's public Object clone() method.