tags:

views:

781

answers:

5

A colleague recently asked me how to deep-clone a Map and I realized that I probably have never used the clone() method- which worries me.

What are the most common scenarios you have found where you need to clone an object?

+4  A: 

Most commonly, when I have to return a mutable object to a caller that I'm worried the caller might muck with, often in a thread-unfriendly way. Lists and Date are the ones that I do this to most. If the caller is likely to want to iterate over a List and I've got threads possibly updating it, it's safer to return a clone or copy of it.

Actually, that brings up something I'm going to have to open up another question for: copy constructors or clone? When I did C++, we ALWAYS did a copy constructor and implemented clone with it, but FindBugs does not like it if you implement your clone using a copy constructor.

Paul Tomblin
If you use a copy constructor to implement clone(), rather than invoking super.clone(), when somebody sub-classes your class and invokes clone they will get an object of the superclass type, not the subclass type.
Dan Dyer
@Dan, yes, that's pretty much what FindBugs said. And having just read something that was linked from a StackOverflow answer to a question about C++, I can now understand that doing it that way in C++ wasn't great.
Paul Tomblin
Implementing clone with copy constructor in C++: Herb Sutter would say "Here be dragons." Read details here: http://www.gotw.ca/publications/advice97.htm
Sébastien RoccaSerra
+3  A: 

When I need to make a duplicate of something to modify the duplicate without impacting the original, and of course in this scenario deep cloning (only) will suffice. I've had to do this on a system where I would clone a domain class instance, apply the user's changes, and then perform a comparison of the two for the user to verify their changes.

cfeduke
+12  A: 

I assume you are referring to Object.clone() in Java. If yes, be advised that 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. You are probably better off defining a copy constructor or a static factory method that explicitly clones the object according to your semantics.

Julien Chastang
Right - the most common scenario is "don't use clone."
Bob Cross
+2  A: 

The Object.clone() method doesn't specify whether the copy of a subclass is a deep or shallow copy, it's completely dependent of the specific class. The Object.clone() method itself does a shallow copy (copies internal state of the Object class), but subclasses must override it, call super.clone(), and copy their internal state as needed (shallow or deep).

It does specify some conventions, which you may or not follow. For (a.getClass() == a.clone().getClass()) to return true, super.clone() should be called instead of simply 'new Subclass()', since super.clone() presumably would correctly instantiate the class of this object (even in subclasses), and copy all internal state, including private fields, which couldn't be copied by subclasses using a copy constructor, due visibility rules. Or you would be forced to expose a constructor that shouldn't be exposed, for better encapsulation.

Example:

//simple clone
class A implements Cloneable {
  private int value;
  public A clone() {
    try {
      A copy = (A) super.clone();
      copy.value = this.value;
      return copy;
    } catch (CloneNotSupportedException ex) {}
  }
}

//clone with deep and shallow copying
class B extends A {
  Calendar date;
  Date date;
  public B clone() {
    B copy = (B) super.clone();
    copy.date = (Calendar) this.date.clone(); // clones the object
    copy.date = this.date; // copies the reference
    return copy;
  }
}

Deep copy is usually used when dependent objects are mutable (like Calendar), and the copy must be completely independent of the original.

When dependent objects are immutable (like Date), sharing the same instance usually isn't an issue, and a shallow copy may be sufficient.

When using Object.clone() you must follow some rules, but they are simple enough to be understandable. Probably the most difficult part is correctly defining how deep you should copy into your object graph. A logical issue, not a language issue, that is.

tetsuo
A: 

I have used Object.clone() in a Spring webflow application to check what has changed when a user edits / enters data on a form for auditing purposes.

At the beginning of the flow, I call the clone method which was implemented on the form backing object used in the spring webflow and save the instance of the clone to the user session. Once the user has completed editing data on the html form and pressed the save button I compare the new values bound to the backing object to the cloned value to determine what data the user has changed.

This worked well and was really easy to implement, I haven't really experienced any issues with cloning in Java.

Neal Donnan