views:

58

answers:

2

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.

+2  A: 

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)

Bozho
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.
aeq
well, then my suggestion about the shallow copy holds ;)
Bozho
clone() worked as expected. I guess I need to revisit why this is so recommended against.
aeq
@aeq - no, don't use clone. see my update
Bozho
+3  A: 

Hello, 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;
  }
}
Bevor
I upvote this on principle, but my comment in the main question is the most important part!
glowcoder
glowcoder, you are right with your question, but I don't know his whole project, so I didn't want to question his intention.
Bevor
Well, SerializationUtils as suggested in my answer does exactly this, but with one line.
Bozho