How to clone objects?

Discussion in 'Java' started by =?iso-8859-1?B?bW9vcJk=?=, Dec 8, 2005.

  1. Hi,
    In my scenerio, building up a class is a difficult task and cost a lot
    of time. I want to store a copy of the object, which has no specific
    detail value. When request the object, I can clone a copy of that and
    use the copy would not affect the original one, so I can change
    whatever value of the cloned one and get another pure clones from the
    original. But I don't know how to use the clone() method suitablely,
    anyone helps? Thx!
     
    =?iso-8859-1?B?bW9vcJk=?=, Dec 8, 2005
    #1
    1. Advertisements

  2. =?iso-8859-1?B?bW9vcJk=?=

    Viator Guest

    I am not commenting on the design that but for that you have to
    implement Cloneable interface.

    Amit :)
     
    Viator, Dec 8, 2005
    #2
    1. Advertisements

  3. =?iso-8859-1?B?bW9vcJk=?=

    J. Verdrengh Guest

    In my experience, the way with the least potential problems is defining a
    new instance method (like YourClass.duplicate() ) or a copy constructor
    (like YourClass.YourClass(YourClass copyMe) ) in which you create a copy of
    <this> / <copyMe>. This way you don't have to think about overriding clone()
    and the consequences of doing that.

    Jeroen
     
    J. Verdrengh, Dec 8, 2005
    #3
  4. =?iso-8859-1?B?bW9vcJk=?=

    Chris Smith Guest

    Cloning is a little complicated. The steps are as follows:

    1. Implement the Cloneable interface.
    2. Override the clone method from Object.
    3. Have the clone method call the superclass.
    4. Have the clone method recursively clone any nonmutable objects that
    are components of this one.
    5. Unless clone is actually likely to fail because of step 4, convert
    CloneNotSupportedException to a RuntimeException.

    It looks like this:

    public class MyPrototype implements Cloneable
    {
    int value; // primitive type
    String name; // reference to immutable object
    Date lastUse; // reference to mutable object
    UserAccount lastUser; // reference to non-component object

    public Object clone()
    {
    try
    {
    MyPrototype other = (MyPrototype) super.clone();
    other.lastUse = lastUser.clone();

    return other;
    }
    catch (CloneNotSupportedException e)
    {
    throw new RuntimeException(e);
    }
    }
    }

    A few notes:

    (a)

    Note that of the four fields, only one had to be explicitly copied in
    the clone() method. In fact, all fields will be copied automatically by
    the call to super.clone(). The thing to remember is that when a field
    is a reference to an object, the reference is copied, and NOT the
    object. So all primitive types are safe.

    If the reference points to an immutable object, that's also safe. The
    object is not copied, so it will be shared between the original and the
    clone. Since it's immutable, though, that is okay. No operations on
    the object can cause it to act differently for the twin. If one of the
    other object reassigns their reference to a different object, the twin
    won't be affected.

    The last two references (lastUse and lastUser, to Date and UserAccount)
    are the more subtle distinction. The Date is actually PART of the
    concept of this object, so it needs to be copied (since Date is mutable)
    to prevent the last use date of this object from being changed when its
    twin is used. The UserAccount, though, is NOT part of the meaning of
    this object. It's just associated with this object. We don't need a
    second UserAccount when cloning this object.

    (b)

    Why swallow the checked exception? Because if someone has a reference
    to MyPrototype, they should be confident that it can be cloned. You
    don't want to force them to handle at compile time the possibility that
    you screwed up and forgot to implement Cloneable or called clone() on a
    non-Cloneable field.

    If you do NOT think they should be confident of this for some reason
    (for example, because you're calling clone() on arbitrary Object
    references that they passed in), then feel free to not swallow the
    exception and document why it won't occur.

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

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 8, 2005
    #4
  5. =?iso-8859-1?B?bW9vcJk=?=

    Chris Smith Guest

    On the other hand, if you want a clone, why would you avoid clone()? If
    this class may have subclasses, then the copy constructor won't work...
    and if its constructors have side-effects, you can't reliably create a
    clone WITHOUT calling Object.clone() at some point. These are the
    problems that clone() was invented to solve.

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

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 8, 2005
    #5
  6. Create a copy constructor for it.Thats the easiest option for you.
     
    The Conqueror, Dec 8, 2005
    #6
  7. =?iso-8859-1?B?bW9vcJk=?=

    zero Guest

    you probably mean other.lastUse = lastUse.clone(); right?

    <snip>

    Seems like a good explanation. Ever think of putting it online? Or maybe
    Roedy could put it on mindprod.
     
    zero, Dec 8, 2005
    #7
  8. =?iso-8859-1?B?bW9vcJk=?=

    J. Verdrengh Guest

    On the other hand, if you want a clone, why would you avoid clone()?

    One reason could be because the semantics of clone() are ambiguous: the same
    method is used for deep copying in one class & shallow copying in another
    class.
     
    J. Verdrengh, Dec 8, 2005
    #8
  9. =?iso-8859-1?B?bW9vcJk=?=

    Chris Smith Guest

    Yes. :) And I messed a necessary cast.

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

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 8, 2005
    #9
  10. =?iso-8859-1?B?bW9vcJk=?=

    Chris Smith Guest

    Once again... if there's every a chance that this class will have
    subclasses, a copy constructor is NOT a reasonable choice.

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

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 8, 2005
    #10
  11. =?iso-8859-1?B?bW9vcJk=?=

    Roedy Green Guest

    Roedy Green, Dec 8, 2005
    #11
  12. =?iso-8859-1?B?bW9vcJk=?=

    Roedy Green Guest

    Are you sure? I think the default clone implementation just copies
    all bytes in the given object. That should produce a cloned subclass
    as well. Has anyone done an experiment to see if clone gives you the
    class where clone was defined or the subclass of the cloned object?
     
    Roedy Green, Dec 9, 2005
    #12
  13. =?iso-8859-1?B?bW9vcJk=?=

    Chris Smith Guest

    You seem to have misunderstood.

    Clone will do the right thing. That is, the class of the resulting
    object is the same as the class of the object that's cloned. This is
    different from a "copy constructor" (C++ terminology) which will produce
    an object of some compile-time known class that may be a superclass of
    the object. In other words, C++ style copy constructors exhibit a
    truncation problem for subclasses, while clone solves that problem.

    (Note that this is fine for the situation in which C++ copy constructors
    are meant to be used... when passing or returning "auto" objectoids
    whose class is necessarily known at compile-time anyway. C++ will never
    apply a copy constructor implicitly when passing pointers to true
    objects. It's just when you try to apply it to true objects that copy
    constructors fail with subclasses.)

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

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 9, 2005
    #13
  14. You also messed this part:
    are components of this one.

    It took me by surprise until I reached the end of the post and realized that
    "nonmutable" was a typo, meant to spell "mutable".

    Alex Molochnikov
    Gestalt Corporation
     
    Alex Molochnikov, Dec 9, 2005
    #14
  15. =?iso-8859-1?B?bW9vcJk=?=

    Chris Smith Guest

    Yes, that's right.

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

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 9, 2005
    #15
  16. =?iso-8859-1?B?bW9vcJk=?=

    Chris Smith Guest

    I would if JINX worked reliably. Roedy is welcome to it, though the
    corrections should be applied.

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

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 9, 2005
    #16
  17. So what? If it is your own class, you implement whatever cloning
    behavior you want in the clone() method.

    /Thomas
     
    Thomas Weidenfeller, Dec 9, 2005
    #17
  18. =?iso-8859-1?B?bW9vcJk=?=

    J. Verdrengh Guest

    you're right
     
    J. Verdrengh, Dec 9, 2005
    #18
  19. Why, when Java gives you both the Object.clone() method and the
    Cloneable interface? Copy constructors are a C++ paradigm.
     
    Darryl L. Pierce, Dec 9, 2005
    #19
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.