All mutable objects referred to by member variables (or objects that you can't be sure won't be externaly mutated) need to be deep copies of their originals.
Primitives and references to immutable objects (or objects you can be sure won't be externally mutated) need not be deep copied (and in fact, deep copy means nothing for primitives).
All classes inherit a clone() function by default. try calling this and seeing if it returns what you want (it returns an Object, which your calling routine will have to cast into the same class type as your class). If not, override the function with your own definition (using the same function signature) where the other advice about what objects (primitives) dont need a deep clone and which do. If you dont understand what I'm saying, look up 'java clone' for examples.
A copy constructor is generally considered a better approach than the clone method. The disadvantage of the copy constructor is you have to know at compile time which class you have, or muck about with reflection.
A copy constructor is generally considered a better
approach than the clone method. The disadvantage of
the copy constructor is you have to know at compile
time which class you have, or muck about with
reflection.
Pardon my ignorance, but what are the advantages of the copy method?
This assumes ALL class variables in the class are set via the constructor. However, if you have the following, the copy constructor is not adequate:
private String name;
public void setName(String name){
this.name=name;
}
You will need to change the copy constructor it as follows:
/* Copy constructor. */
public Galaxy(Galaxy aGalaxy) {
this(aGalaxy.getMass(), aGalaxy.getName());
this.name= aGalaxy.getName();
}
That is to say, you will have to set any other class variables not specifically set in the constructor.
Buy the way, I like the copy constructor better than clone() because I never liked having the caller cast the return of clone into the correct type.
This assumes ALL class variables in the class are set
via the constructor.
Well, the point of a copy c'tor is to make a new object that has the same state as the original. If you don't do it, that's just a bug in your copy c'tor.
Another option is to serialize the object and then unserialize it to a new instance. The disadvantages to this method are that all objects referenced by the main object must be serializable and serialization is not the most efficient method.
Using serialization to clone an object may not be considered a GoodThing(TM) ? you might what to do a Google search to see if there are other advantages or disadvantages (I recall some article on the subject).
A copy constructor is generally considered a better
approach than the clone method. The disadvantage of
the copy constructor is you have to know at compile
time which class you have, or muck about with
reflection.
I have to disagree with you here (and with the article you referenced later).
First, as you noted, with the copy ctor you have to know the object's type beforehand. And if you happen to have an instance of a subclass, you're going to lose all the subclass-specific data.
The referenced article claims that "clone is very tricky to implement correctly in all circumstances, nearly to the point of being pathological," but I'd claim that a copy constructor is at least as difficult.
In both cases, you have to ensure that all contained mutable objects are correctly copied (deep versus shallow), and that the copy proceeds recursively (for example, if you have a collection, you can't just copy the collection, you have to copy its members as well, and their contents, and so on).
Clone also became a little easier to use with 1.5, with the introduction of covariant return types: you no longer need to cast its result.
As another poster mentioned, serialization is an easy way to implement a clone() method, although it will be a little too aggressive, creating new instances of immutable objects. On the positive side, it keeps track of objects that appear multiple times in the graph, so will not break any assumptions about identity.
I've ended up implementing a clone helper method, which uses reflection to recursively traverse an object graph, copying mutable objects and preserving object identity. It's probably a little faster than using serialization, and seems more correct to me, but took several thousand lines of unit test code to get right.
To be honest, I've never really understood what the big bad deal was with cloning. I'm just toeing the party line saying the copy c'tors are better. It seems like one of those things I knew at one point but forgot the reasons for.