tags:

views:

3493

answers:

7

In java it's a bit difficult to implement a deep object copy function. What steps you take to ensure the original object and the cloned one share no reference?

+8  A: 

A safe way is to serialize the object, then deserialize. This ensures everything is a brand new reference.

Here's an article about how to do this efficiently.

Caveats: It's possible for classes to override serialization such that new instances are not created, e.g. for singletons. Also this of course doesn't work if your classes aren't Serializable.

Jason Cohen
Be aware that the FastByteArrayOutputStream implementation provided in the article could be more efficient. It uses an ArrayList-style expansion when the buffer fills up, but it's better to use a LinkedList-style expansion approach. Instead of creating a new 2x buffer and memcpy-ing the current buffer over, maintain a linked list of buffers, adding a new one when the current fills up. If you get a request to write more data than would fit in your default buffer size, create a buffer node that is exactly as large as the request; the nodes don't need to be the same size.
Brian Harris
+2  A: 

Deep copying can only be done with each class's consent. If you have control over the class hierarchy then you can implement the clonable interface and implement the Clone method. Otherwise doing a deep copy is impossible to do safely because the object may also be sharing non-data resources (e.g. database connections). In general however deep copying is considered bad practice in the Java environment and should be avoided via the appropriate design practices.

Orion Adrian
+1  A: 

You can do a serialization-based deep clone using org.apache.commons.lang.SerializationUtils.clone() in Commons Lang, but be careful--the performance is abysmal.

In general, it is best practice to write your own clone methods for each class of an object in the object graph needing cloning.

+1  A: 

Use XStream(http://xstream.codehaus.org/). You can even control which properties you can ignore through annotations or explicitly specifying the property name to XStream class. Moreover you do not need to implement clonable interface.

Adi
+1  A: 

XStream is really useful in such instances. Here is a simple code to do cloning

private static final XStream XSTREAM = new XStream();
...

Object newObject = XSTREAM.fromXML(XSTREAM.toXML(obj));
sankara
+7  A: 

A few people have mentioned using or overriding Object.clone(). Don't do it. Object.clone() has some major problems, and its use is discouraged in most cases. Please see Item 11, from "Effective Java" by Joshua Bloch for a complete answer. I believe you can safely use Object.clone() on primitive type arrays, but apart from that you need to be judicious about properly using and overriding clone.

The schemes that rely on serialization (XML or otherwise) are kludgy.

There is no easy answer here. If you want to deep copy an object you will have to traverse the object graph and copy each child object explicitly via the object's copy constructor or a static factory method that in turn deep copies the child object. Immutables (e.g. Strings) do not need to be copied. As an aside, you should favor immutability for this reason.

Julien Chastang