Java object copy best option? [duplicate]
Asked Answered
G

3

5

Possible Duplicate:
How do I copy an object in Java?

I need to copy an object in Java (i.e. copy the object "by value not by reference" so that the new object is not just a reference to the old). I'm weary of implementing clonable and would prefer to use a copy constructor. However, the class I need to copy has MANY member variables that need to be copied (over 100) so adding a new constructor to the class just for copying (which is only needed in a 1 part of my application) seems like a poor solution due to its enourmous length.

Is there a better solution? Should I just use clone()? Can I create a copy constructor but rather than copying all the fields over 1 by 1 can I do it reflectively? Thanks.

I basically just need to create a new object that is the same as the old one, but with a few (about 10 out of 100) fields changed (but I still need both objects..so the new one cannot be a reference to the old one). I am open to any suggestions.

Groves answered 29/6, 2010 at 20:57 Comment(4)
Do you really need 100 member variables? Maybe Map or List will do a better job.Welton
Yes, the class represents columns of one of my DB tables. You are right that there may be a better solution, but this class is already deeply tied into a large application. I just need to add copying capability.Groves
Over 100 columns!? Damn, it goes beyond the worse case I ever imagined!Mailemailed
Just because it's embedded doesn't mean it's not modifiable. That's why you're using OOP. Perhaps some of those member variables can be grouped together into container classes for better management, especially if they can be used elsewhere. Also, perhaps your DBA should look into normalization. If you have 100 columns, I promise you there's lots of repeated data that can be normalized. Once normalized, it should be easy to break it down into more useful, reusable classes, each of which can easily have their own copy constructor or other copy mechanism.Predominant
B
11

clone() makes a shallow clone - it copies only the first level of fields. You should avoid using clone() and Cloneable, because it is very hard to implement it correctly, and it is very likely that something will be broken, although not immediately visible. See what Joshua Bloch says about this.

If you want deep copy - i.e. the whole object hierarchy being cloned, I can suggest two options:

If however, you want shallow copy - i.e. you still want all your fields copied to a new object, but the fields, and the fields' fields (etc..) point to their original values, then you can use BeanUtils.clone(..) (from commons-beanutils)

Apart from the cloning matter - having 100 member variables isn't a good sign. Consider splitting your class into multiple classes (update: and multiple tables, using foreign keys. Of course, if that is applicable. If these are truly properties of the same object, then fine)

Brigitte answered 29/6, 2010 at 21:3 Comment(4)
I removed the wording "deep clone" from my post as I dont think this is what I meant. I just need the member variables copied over.Groves
well, then my suggestion about the shallow copy holds ;)Brigitte
clone() worked as expected. I guess I need to revisit why this is so recommended against.Groves
@Groves - no, don't use clone. see my updateBrigitte
C
8

one option can be to use a serialization. It's not the fastest one but probably one of the safest. Look at the code on this site:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectputStream;
import java.io.ObjectOutputStream;

public class DeepObjectCopy {

  public static Object clone(Object copyObject) {
    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(copyObject);
      ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
      ObjectputStream ois = new ObjectputStream(bais);
      Object deepCopy = ois.readObject();
      return deepCopy;
    } catch (IOException e) {
      e.printStackTrace();
    } catch(ClassNotFoundException e) {
      e.printStackTrace();
    }
    return null;
  }
}
Crews answered 29/6, 2010 at 21:6 Comment(3)
I upvote this on principle, but my comment in the main question is the most important part!Predominant
glowcoder, you are right with your question, but I don't know his whole project, so I didn't want to question his intention.Crews
Well, SerializationUtils as suggested in my answer does exactly this, but with one line.Brigitte
B
0

BeanUtils methods are based on reflection, so they are (relatively) slow. So is dozer and other similar tools. Copying constructor is the fastest way to do your task so if you're not coding for platform such as Android when each kb of code is an issue, you should choose that way. If the only problem is writing copy constructors, you can use Eclipse plugins such as JUtils.

Buyer answered 23/3, 2012 at 8:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.