Wanted: generic deep copy for clone()

Discussion in 'Java' started by Tim Tyler, Jul 8, 2003.

  1. Tim Tyler

    Tim Tyler Guest

    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 ;-) ;-)
    --
    __________
    |im |yler http://timtyler.org/
     
    Tim Tyler, Jul 8, 2003
    #1
    1. Advertising

  2. Tim Tyler

    Jacob Guest

    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 cannot give you the code as it is commercial.
     
    Jacob, Jul 8, 2003
    #2
    1. Advertising

  3. Tim Tyler

    Tim Tyler Guest

    Jacob <> wrote:
    : 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?
    --
    __________
    |im |yler http://timtyler.org/
     
    Tim Tyler, Jul 8, 2003
    #3
  4. Tim Tyler

    Steve Guest

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

    On Tue, 8 Jul 2003 12:43:58 GMT, Tim Tyler <> wrote:

    >Jacob <> wrote:
    >: 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
    ~
     
    Steve, Jul 8, 2003
    #4
  5. Tim Tyler

    Roedy Green Guest

    On Tue, 8 Jul 2003 07:37:00 GMT, Tim Tyler <> wrote or
    quoted :

    >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.

    --
    Canadian Mind Products, Roedy Green.
    Coaching, problem solving, economical contract programming.
    See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
     
    Roedy Green, Jul 8, 2003
    #5
  6. Tim Tyler

    Harald Hein Guest

    "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. 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
     
    Harald Hein, Jul 8, 2003
    #6
  7. Tim Tyler

    Tim Tyler Guest

    Harald Hein <> wrote:
    : "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 :->]
    --
    __________
    |im |yler http://timtyler.org/
     
    Tim Tyler, Jul 8, 2003
    #7
  8. Tim Tyler

    Filip Larsen Guest

    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();
    }



    --
    Filip Larsen
     
    Filip Larsen, Jul 8, 2003
    #8
  9. Tim Tyler

    Tim Tyler Guest

    Filip Larsen <> wrote:
    : 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...
    --
    __________
    |im |yler http://timtyler.org/
     
    Tim Tyler, Jul 8, 2003
    #9
  10. Tim Tyler

    Tim Tyler Guest

    Tim Tyler <> wrote:
    : Jacob <> wrote:

    : : 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.
    --
    __________
    |im |yler http://timtyler.org/
     
    Tim Tyler, Jul 9, 2003
    #10
  11. Tim Tyler

    Filip Larsen Guest

    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.


    --
    Filip Larsen
     
    Filip Larsen, Jul 9, 2003
    #11
  12. Tim Tyler

    Tim Tyler Guest

    Chris <> wrote:

    : 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.
    --
    __________
    |im |yler http://timtyler.org/
     
    Tim Tyler, Jul 9, 2003
    #12
  13. 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

    "Tim Tyler" <> wrote in message news:...
    > Patrick Meuser <> wrote:
    >
    > : Of course all of your objects must implement Serializable in order for

    this
    > : to work consistently.
    >
    > Typically none of the objects I'm involved with implement Serializable.
    >
    > Implementing Serializable is about as much work as implementing clone
    > (or maybe more?).
    >
    > It too has the same maintainability problems - if you add a field you
    > have to update your serailisation method to stop things getting out of
    > step.
    >
    > I'm after something that will do all this automatically - using
    > reflection - based on the structure of the class.
    > --
    > __________
    > |im |yler http://timtyler.org/
     
    Patrick Meuser, Jul 9, 2003
    #13
  14. Tim Tyler

    Doug Pardee Guest

    Tim Tyler <> wrote:
    > 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.
     
    Doug Pardee, Jul 10, 2003
    #14
  15. Tim Tyler

    Chris Guest

    > 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
     
    Chris, Jul 10, 2003
    #15
  16. Tim Tyler

    Doug Pardee Guest

    Tim Tyler <> wrote:
    > 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.
     
    Doug Pardee, Jul 10, 2003
    #16
  17. Tim Tyler

    Tim Tyler Guest

    Doug Pardee <> wrote:
    : Tim Tyler <> wrote:

    :> 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?
    --
    __________
    |im |yler http://timtyler.org/
     
    Tim Tyler, Jul 10, 2003
    #17
  18. Tim Tyler

    Tim Tyler Guest

    Chris Smith <> wrote:
    : 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 ;-)
    --
    __________
    |im |yler http://timtyler.org/
     
    Tim Tyler, Jul 10, 2003
    #18
  19. Tim Tyler

    Chris Smith Guest

    Tim Tyler wrote:
    > Tim Tyler <> wrote:
    >
    > : 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
     
    Chris Smith, Jul 10, 2003
    #19
  20. Tim Tyler

    Tim Tyler Guest

    Tim Tyler <> wrote:
    : Chris <> wrote:

    : : 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.
    --
    __________
    |im |yler http://timtyler.org/
     
    Tim Tyler, Jul 11, 2003
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Harvey
    Replies:
    0
    Views:
    790
    Harvey
    Jul 16, 2004
  2. Harvey
    Replies:
    1
    Views:
    896
    Daniel
    Jul 16, 2004
  3. Replies:
    4
    Views:
    3,918
    Roedy Green
    Dec 24, 2005
  4. Alex
    Replies:
    2
    Views:
    1,287
  5. Replies:
    26
    Views:
    2,175
    Roland Pibinger
    Sep 1, 2006
Loading...

Share This Page