Wanted: generic deep copy for clone()


T

Tim Tyler

Object.clone() does a shallow copy.

Nine times out of ten I want a deep copy.

I'm fed up with writing my own deep copy code for each class.

What I want is never to have to write deep copy clone methods again.

Has anyone got some generic Object deep copy code - that will deep
copy an arbitrary object - using reflection?

I know that some objects might in principle require bizzare
constructor or factory calls to copy.

The hoped-for deep copy code is welcome to expect primitives, objects
with clone methods - or collections or arrays of the above - and
is welcome to throw some CloneChallengedException if it finds things
are beyond its scope.

When you're done with that I'll take another method that calcutates
hash codes - by a combination of feeding leaf primitives through
a CRC/Cr# - and calling object hash code methods recursively, and
#ing the results together ;-) ;-)
 
Ad

Advertisements

J

Jacob

Tim said:
Has anyone got some generic Object deep copy code - that will deep
copy an arbitrary object - using reflection?

I have done a simple implementation of this.
The code assumes that fields to copy have
appropriate get/set methods and find and
call those using inspection.

I cannot give you the code as it is commercial.
 
T

Tim Tyler

: Tim Tyler wrote:

:> Has anyone got some generic Object deep copy code - that will deep
:> copy an arbitrary object - using reflection?

: I have done a simple implementation of this.

: The code assumes that fields to copy have
: appropriate get/set methods and find and
: call those using inspection.

I guess that's not unreasonable.

Public fields would be nice as well, though ;-)

: I cannot give you the code as it is commercial.

OK - anyone else?
 
S

Steve

http://www.google.com/search?hl=en&...fe=on&q=generic+deep+copy+&btnG=Google+Search

: Tim Tyler wrote:

:> Has anyone got some generic Object deep copy code - that will deep
:> copy an arbitrary object - using reflection?

: I have done a simple implementation of this.

: The code assumes that fields to copy have
: appropriate get/set methods and find and
: call those using inspection.

I guess that's not unreasonable.

Public fields would be nice as well, though ;-)

: I cannot give you the code as it is commercial.

OK - anyone else?


~ If emailing, please use: Steve_A_Haigh
~ @
~ hotmail.com
~
 
R

Roedy Green

Has anyone got some generic Object deep copy code - that will deep
copy an arbitrary object - using reflection?

What might also work is something that generates code you compile.
That would be far faster than using reflection every time you have to
clone.
 
H

Harald Hein

Tim Tyler said:
Object.clone() does a shallow copy.

Not exactly. The default behavior of Object.clone() is a shallow
copy. But what exactly happens in the clone() method of a subclass
entirely depends on the implementation in the subclasses. Some people
choose to implement deep copying in clone(), others don't.

The problem with clone() is that its semantics is "defined" as

Quote from the API spec:

The precise meaning of "copy" may depend on the class of the
object. The general intent is ... but these are not
absolute requirements. While it is typically the case that:
..., this is not an absolute requirement.

In other words, nothing, absolutely nothing, is specified.

HH
 
Ad

Advertisements

T

Tim Tyler

: "Tim Tyler" wrote:

:> Object.clone() does a shallow copy.

: Not exactly. The default behavior of Object.clone() is a shallow
: copy. But what exactly happens in the clone() method of a subclass
: entirely depends on the implementation in the subclasses. [...]

When I referred to "Object.clone()" I meant the clone method in
the "Object" class.

[please don't anyone tell me that Object.clone is not static :->]
 
F

Filip Larsen

Tim Tyler wrote
Has anyone got some generic Object deep copy code - that will deep
copy an arbitrary object - using reflection?

If the objects you want to clone all supports serialization you should be
able to use that mechanism for a deep copy. For example something along the
following lines:

public Object deepCopy(Object objectTree) throws IOException,
ClassNotFoundException {
ByteArrayOutputStream outStore = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOuputStream(outStore);
out.writeObject(objectTree);
ByteArrayInputStream inStore = new
ByteArrayInputStream(outStore.toByteArray());
ObjectInputStream in = new ObjectInputStream(inStore);
return in.readObject();
}
 
T

Tim Tyler

: Tim Tyler wrote

:> Has anyone got some generic Object deep copy code - that will deep
:> copy an arbitrary object - using reflection?

: If the objects you want to clone all supports serialization you should be
: able to use that mechanism for a deep copy. For example something along the
: following lines:

: public Object deepCopy(Object objectTree) throws IOException,
: ClassNotFoundException {
: ByteArrayOutputStream outStore = new ByteArrayOutputStream();
: ObjectOutputStream out = new ObjectOuputStream(outStore);
: out.writeObject(objectTree);
: ByteArrayInputStream inStore = new
: ByteArrayInputStream(outStore.toByteArray());
: ObjectInputStream in = new ObjectInputStream(inStore);
: return in.readObject();
: }

That makes me smile.

I feel like it has just move the goalposts, though.

Now to execute my plan I need a means of serialising an object
automatically - using reflection to access the fields...
 
T

Tim Tyler

: : The code assumes that fields to copy have
: : appropriate get/set methods and find and
: : call those using inspection.

: I guess that's not unreasonable.

: Public fields would be nice as well, though ;-)

In fact all fields should be doable - in principle - I believe.

One problem might be that the reflection involved would mean
that the code would no longer work in certain SecurityManagers
that prohibit reflection operations.

I suspect this would be a bit of an irritation.
 
F

Filip Larsen

Tim Tyler wrote
:> Has anyone got some generic Object deep copy code - that will deep
:> copy an arbitrary object - using reflection?

: If the objects you want to clone all supports serialization you should be
: able to use that mechanism for a deep copy.

Now to execute my plan I need a means of serialising an object
automatically - using reflection to access the fields...

Serialization was designed to work with a minimum of co-operation from
the programmers hand; in most cases your classes only need to be
marked as Serialiazable for it to work. See java.io.Serializable and
the Object Serialization documentation part of a J2SE release for more
details.

I understand that you feel you are just swapping one problem for
another. I can only say, that if the instances you want to clone
aren't serializable, then there is a good chance that they don't have
a sensible clone semantics either, or that their programmer simply
"forgot" to address the issue. Even if it is technically possible to
write a component to deep clone objects without their co-operation
(which it probably is), I don't believe it necessarily would be a good
idea to do so, and this for the same reasons Object Serialization
don't do it.
 
Ad

Advertisements

T

Tim Tyler

: I'd also consider why you're needing this deep copy before you go to
: all the trouble of some of the above suggestions, not to mention the
: implications on your code: all serializable (not necessarily a bad
: thing), all classes require clone(), etc.

: I'm worked in Java for over 5 years now on a variety of applications
: and I've never written a clone() method yet. So why do ALL your
: classes need to be cloneable?

Not all my classes need to be clonable.

I never suggested they did - AFAICS.

If you have never cloned anything of your own then that is probably a
cause for you to reexamine your coding strategy.

Clone in Java has more than its share of dumb screw-ups - but I believe
the consensus is that it's better than using copy constructors
(these are even more badly screwed up) - or rolling your own solution
using factory methods and an interface (then there's no default
implementation availible).

Also, any other solution these days would also mean that you can't
interop with other classes which use clone.

http://www.artima.com/intv/issuesP.html goes into some of the clone
screw-ups - but still seems to wind up recommending that you use it.
 
P

Patrick Meuser

Using serialization has its advantages. First it supports a native
mechanism to access fields that you cannot in reflection, you need not
implement anything in order to implement Serializable, just know that all of
the class' members implement serializable as well..

"The default serialization mechanism for an object writes the class of the
object, the class signature, and the values of all non-transient and
non-static fields. References to other objects (except in transient or
static fields) cause those objects to be written also. Multiple references
to a single object are encoded using a reference sharing mechanism so that
graphs of objects can be restored to the same shape as when the original was
written. " -- ObjectOutputStream JAVADOC

With reflection, consider the following:

class Foo
{
private String member="bar";
}
class Bar
{
public class bar() throws Exception
{
Foo foo=new Foo();
Field member=foo.getClass().getDeclaredField("member");
String bar=member.get(foo); // throws IllegalAccessException because
member is private
}
}

The crux of the problem seems to be that you have existing classes that
cannot be reimplemented or refactored to support reflection or serialization
as to access the internal state and make a deep clone. If you change the
class somehow, serializable works automatically by some magic of the JVM to
maintain an image via a default IO mechanism (see
ObjectOutputStream.defaultWriteObject) however the class signature would
vary across versions, not a problem here as we only make copy and throw away
the buffer, however all of the objects must implement the Serializable
interface ex.

class Foo implements Serializable
{
private String member="bar";
}

The only hope here is some debug API you could use to inspect all the
members that maintain state and make a copy with that. Again you would
likely have to make sure that you have a default constructor in each of the
classes which could be as much as a pain as implementing Serializable.

All of this unless you have a public API for as much such as an accessor
method for each non-transient memeber variable (which would likely be all of
them), then things are fairly straightforward..

Good luck,

Patrick Meuser
 
D

Doug Pardee

Tim Tyler said:
Object.clone() does a shallow copy.

Nine times out of ten I want a deep copy.

I'm fed up with writing my own deep copy code for each class.

What I want is never to have to write deep copy clone methods again.

Has anyone got some generic Object deep copy code - that will deep
copy an arbitrary object - using reflection?

Deep copying is an interesting problem. Ask the people who have had to
implement it in Eiffel, where the universal base class provides
deep_copy and deep_clone methods for all object classes:

"It is useful, in some cases, to duplicate not just one object but
an entire object structure. The expression deep_clone(y) achieves
this goal: assuming non-void y, it will produce a duplicate not
just of the object attached to y but of the entire object structure
starting at that object. The mechanism respects all the possible
details of that structure, such as cyclic reference chains."
(http://docs.eiffel.com/general/guided_tour/language/tutorial-07.html)

Not all object trees are directed acyclic graphs. Trying to clone
bi-linked lists and circular lists, for instance, gives rise to some
amusing results if the clone operation isn't prepared for the
situation. The deep-clone operation typically ends up being a
multi-pass affair: first it shallow-clones each of the objects while
being careful to ignore objects already cloned, then it updates all of
the references in all of the cloned objects.

Deep-cloning becomes even more amusing in the multi-threaded Java
environment, where there is no way for a generic deep-clone mechanism
to know what monitor object is being used to control access to each of
the objects being cloned. For that matter, even if it knew the monitor
objects, the clone mechanism does not dare use them, lest it cause a
deadlock.

Basically, if you want to deep-clone an object, that object's class
might need to provide custom handling for the cloning operation.
There's no way to write a generic deep-clone mechanism that works for
all cases.

Notice that all of the problems mentioned above apply equally to
serialization, which is why java.io.Serialiazable provides
readObject(), writeObject(), readResolve(), and writeReplace() methods
that can be implemented by classes that are aware of complications.
 
C

Chris

If you have never cloned anything of your own then that is probably a
cause for you to reexamine your coding strategy.

Probably depends on the type of projects - I've generally worked on
large back-end / server-side applications, and I've never used (or
seen any code that anyone else has designed) use clone. But I guess
that GUI / front-end code would require copying.
Clone in Java has more than its share of dumb screw-ups - but I believe
the consensus is that it's better than using copy constructors
(these are even more badly screwed up) - or rolling your own solution
using factory methods and an interface (then there's no default
implementation availible).

Would agree with that though. A bespoke solution (factories,
interface) always adds additional complexity, leading to faults and
maintenance issues.

- sarge
 
D

Doug Pardee

Tim Tyler said:
If you have never cloned anything of your own then that is probably a
cause for you to reexamine your coding strategy.

If you HAVE ever cloned anything in Java, then that is probably a
cause for you to reexamine your understanding of OO and Java.

Cloning an immutable object is pointless.

Mutable classes should be used for objects that are known by their
identity. Cloning objects of those classes is generally a Bad Thing,
because that defeats the whole point of an identity object.

Where I usually see cloning being used is when someone has created a
value class and failed to make the class immutable. This should be
fixed by making the value class immutable. If fixing the class is not
an option, then the objects of that class should be wrapped with an
immutable proxy; cloning the mutable value objects is a poor second
choice because of the high potential for encountering aliasing bugs.

Cloning of identity objects is also found in the GoF Prototype
pattern. Unfortunately, if the prototype can be cloned, so can the
cloned instances, and as already noted that is generally a Bad Thing.
Factories provide a clean alternative.
 
Ad

Advertisements

T

Tim Tyler

:> If you have never cloned anything of your own then that is probably a
:> cause for you to reexamine your coding strategy.

: If you HAVE ever cloned anything in Java, then that is probably a
: cause for you to reexamine your understanding of OO and Java.

!??

: Cloning an immutable object is pointless.

: Mutable classes should be used for objects that are known by their
: identity. Cloning objects of those classes is generally a Bad Thing,
: because that defeats the whole point of an identity object.

This seems very confused to me. What's to stop me from wanting
a second object that is a slight modificaiton of an existing,
mutable one?

java.util.BitSet
java.util.Calendar
java.util.Date
java.util.HashMap
java.util.Hashtable
java.util.LinkedList
java.util.Locale
java.util.TimeZone
java.util.TreeMap
java.util.TreeSet
java.util.Vector

....are all "cloneable".

If cloning is such bad practice shouldn't someone inform Sun microsystems?
 
T

Tim Tyler

: Tim Tyler wrote:

:> Has anyone got some generic Object deep copy code - that will deep
:> copy an arbitrary object - using reflection?

: Well, I won't give you that, but I'll give you something sorta related.
: I think there's something inherently wrong with wanting what you asked
: for. Allow me to explain...

: The point of the clone() method (though it certainly has its problems)
: is that it confines knowledge of how to copy object state to the class
: that defines that object state. With the code you're asking for, you
: have to know, from outside the object, whether it should be copied in a
: shallow or deep way.

: Instead, the best way to go (IMO of course) is to make it as easy as
: possible to implement clone() according to the original plan. To that
: end, I provide you with the following code:

That is - essentially - what I was visualising originally.

I'm not quite sure what you are suggesting I was asking for -
but your code is basically what I was thinking of.

It appears that now I have two methods of doing what I asked after -
all I have to do now if figure out the pros and cons of each one ;-)
 
C

Chris Smith

Tim said:
: It appears that now I have two methods of doing what I asked after -
: all I have to do now if figure out the pros and cons of each one ;-)

It seems to me a possible variant on this code would be to
catch what I presume is a RuntimeException at
the: f.setAccessible(true); line - and then catch the possible
IllegalAccessException and attempt access using get and set calls
based on the name of the field.

That would help deal with the case where the SecurityManager chokes
on the setAccessible(true); line.

That would be possible (incidentally, it throws a SecurityException,
which is a subclass of RuntimeException). To me, that seems like it's
crossing a line, making assumptions that the implementor followed the
JavaBeans specification and that all important state is accessible
through JavaBeans. If I were going to make such an assumption, I'd just
go all-out and use java.beans.Introspector to do all the work.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
Ad

Advertisements

T

Tim Tyler

: : I'd also consider why you're needing this deep copy before you go to
: : all the trouble of some of the above suggestions, not to mention the
: : implications on your code: all serializable (not necessarily a bad
: : thing), all classes require clone(), etc.

: : I'm worked in Java for over 5 years now on a variety of applications
: : and I've never written a clone() method yet. So why do ALL your
: : classes need to be cloneable?

: Not all my classes need to be clonable.

: I never suggested they did - AFAICS.

However, I /did/ write:

``I'm fed up with writing my own deep copy code for each class.

What I want is never to have to write deep copy clone methods again.

Has anyone got some generic Object deep copy code - that will deep
copy an arbitrary object - using reflection?''

I can see how this might suggest that:

* I was writing deep copy code for /every/ class;
* I wanted to copy "arbitrary object"s.

I just want to find an easier way to clone those classes I want to
make Cloneable - without writing "clone" methods out in longhand
over and over again.

My apologies for any confusion due to my poor expression of this aim.
 

Top