Object cloning question

Hello all,

I have a question about cloning a class. My class is something like this...

publicclass Messageimplements Cloneable

{

int id;

Fields fromClient;

Fields fromProcessor;

Fields toClient;

Fields toProcessor;

protected Object clone()throws CloneNotSupportedException

{

return (super.clone());

}

}

FYI, the Fields object is another class that contains a Vector of Field objects... A Field is simple class containing three strings, one string namedname, one is namedvalue, the other string is nameddefaultValue.

At application startup, I create this class and each of the Fields objects are initialized with various Field object stuff.

Message baseMessage =new Message();

Later in the process, when I need to create a new Message object, instead of doing a 'new' I instead do a

Message msg1 = baseMessage.clone();

The newly cloned msg1 object is then processed and manipulated.

The problem I am having is that on the next call to

Message msg2 = baseMessage.clone();

the newly cloned msg2 object contains the contents of msg1! This is very strange because I thought that msg2 would be a clone of baseMessage which does not contain any of the information found in msg1...

Any ideas? I hope I explained it well enough...

Thanks,

-Jeff

[1798 byte] By [k0balta] at [2007-11-27 0:35:26]
# 1
At a Guess I would say that msg1 is sharing the Fields objects in baseMessage.
ChristopherAngela at 2007-7-11 22:43:52 > top of Java-index,Java Essentials,Java Programming...
# 2

clone() is shallow unless you make it otherwise. What that means is message.clone()

returns a reference to a new message object whose field values are copies of the originals. Remember that an object's fields are references, NOT other objects. So now you have two Message objects, and both of their fromClient fields point to the same Fields object, etc.

If you want new Fields objects, you'd have to do something like this:

protected Object clone() throws CloneNotSupportedException {

Message result = (Message)super.clone();

result.fromClient = (Fields)fromClient.clone();

etc.

return result;

}

Likewise, if you wanted the cloned Fields objects to have their own Vectors (and why are you using Vector rather than ArrayList?), then Fields' clone() method would have to dupe the Vectors.

Also, did you realy intend your clone() method to be protected?

jverda at 2007-7-11 22:43:52 > top of Java-index,Java Essentials,Java Programming...
# 3
Well something happened to the posts... Several posts are no longer here!!!!!Anyways. I think that everyone is right about the shallow copy vs the deep copy... I will look into this...
k0balta at 2007-7-11 22:43:52 > top of Java-index,Java Essentials,Java Programming...
# 4
> Also, did you realy intend your clone() method to be protected?I am not really sure why a make the clone() protected. I most likely read somewhere that it needed to be protected... Is this a bad thing?
k0balta at 2007-7-11 22:43:52 > top of Java-index,Java Essentials,Java Programming...
# 5

> Well something happened to the posts... Several

> posts are no longer here!!!!!

>

> Anyways. I think that everyone is right about the

> shallow copy vs the deep copy... I will look into

> this...

embla often gets her posts deleted because she posts insulting, inflammatory nonsense with no technical value. When that happens, responses and responses to responses, etc., to the deleted posts get hosed too.

jverda at 2007-7-11 22:43:52 > top of Java-index,Java Essentials,Java Programming...
# 6

> > Also, did you realy intend your clone() method to

> be protected?

>

> I am not really sure why a make the clone()

> protected. I most likely read somewhere that it

> needed to be protected... Is this a bad thing?

Not necessarily. It depends on who you want to be able to clone your object. If you want everbody to be able to, make it public. If you want only classes in that package and subclasses of your class to be able to do it, make it protected. I just wondered because public is probably more common.

As for your other comment about why you weren't using new: You can still use new to make a deep or shallow copy. It's called a copy constructor.

public class Message {

public Message(Message orig) {

field1 = orig.field1; // shallow copy

field2 = new Field2(orig.field2); // deep copy, assuming Field2 has such a constructor

etc.

}

}

jverda at 2007-7-11 22:43:52 > top of Java-index,Java Essentials,Java Programming...
# 7
> Anyways. I think that everyone is right about the> shallow copy vs the deep copy... I will look into> this...Clone() definitely makes a shallow copy, unless you implement it to do differently. Whether you need a shallow or deep copy is up to you.
jverda at 2007-7-11 22:43:52 > top of Java-index,Java Essentials,Java Programming...
# 8
Oh, OK, I thought it was strange that several posts were deleted. Thanks for the clarification...
k0balta at 2007-7-11 22:43:52 > top of Java-index,Java Essentials,Java Programming...
# 9

>Likewise, if you wanted the cloned Fields objects to have their own Vectors

>(and why are you using Vector rather than ArrayList?), then Fields' clone()

>method would have to dupe the Vectors.

As for your question about using Vector rather than ArrayList... I have never used an ArrayList before, just Vectors.

k0balta at 2007-7-11 22:43:53 > top of Java-index,Java Essentials,Java Programming...
# 10

> As for your question about using Vector rather than

> ArrayList... I have never used an ArrayList before,

> just Vectors.

ArrayList and HashMap are generally preferred over Vector and Hashtable, as they were created as part of the Collections Framework in 1.2, while the other two predate the Framework and were retrofitted into it.

jverda at 2007-7-11 22:43:53 > top of Java-index,Java Essentials,Java Programming...
# 11
My bad, I am not using a Vector... I am using a LinkedList instead...
k0balta at 2007-7-11 22:43:53 > top of Java-index,Java Essentials,Java Programming...
# 12
> My bad, I am not using a Vector... I am using a> LinkedList instead...LL is fine. AL is simply the closest replacement for Vector, as they're both backed by arrays.
jverda at 2007-7-11 22:43:53 > top of Java-index,Java Essentials,Java Programming...
# 13
WOW, this has really thrown a wrench into things...I guess I assumed to much when it came to the clone() method...
k0balta at 2007-7-11 22:43:53 > top of Java-index,Java Essentials,Java Programming...
# 14

The problem is coming down to duping the Fields LinkList, in the clone() method. I am not quite sure how to do that...

Here is that I have:

public class Message implements Cloneable

{

String name;

Fields fromClient;

Fields fromProcessor;

Fields toClient;

Fields toProcessor;

}

public class Fields implements Cloneable

{

LinkedList fields;

}

public class Field

{

String defaultValue = null;

String name = null;

String value = "";

}

Any ideas or pointers?

k0balta at 2007-7-11 22:43:53 > top of Java-index,Java Essentials,Java Programming...
# 15

Something like this?

import java.util.*;

class Field implements Cloneable {

public Field clone() {

try {

Field copy = (Field) super.clone();

//...

return copy;

} catch (CloneNotSupportedException e) {

throw new InternalError(e.getMessage());

}

}

}

public class Fields implements Cloneable {

private List<Field> fields;

public Fields clone() {

try {

Fields copy = (Fields) super.clone();

if (copy.fields != null) {

copy.fields = new ArrayList < Field > ();

for(Field f : fields) {

copy.fields.add(f.clone());

}

}

return copy;

} catch (CloneNotSupportedException e) {

throw new InternalError(e.getMessage());

}

}

}

DrLaszloJamfa at 2007-7-21 19:49:28 > top of Java-index,Java Essentials,Java Programming...
# 16
After further reading, it looks like the clone() method is not really a liked method and that the Copy constructor is. You did mention using a Copy. I will delve into that Copy constructor a little more...
k0balta at 2007-7-21 19:49:28 > top of Java-index,Java Essentials,Java Programming...
# 17
AH HA, that was my problem. I had something like that, but I did not actually copy each of the Field objects individually...I really appreciate the help... Let me give this a try...
k0balta at 2007-7-21 19:49:28 > top of Java-index,Java Essentials,Java Programming...
# 18
Some people prefer copy constructors, others prefer clone. Take your choice. They each have their pluses and minuses.
DrLaszloJamfa at 2007-7-21 19:49:28 > top of Java-index,Java Essentials,Java Programming...
# 19

One place where clone (or you own copy method) is better than a copy

constructor is when you need to do polymorphic copying. Suppose

you have a collection of Shapes, and you want to copy it.

Copy constructors wouldn't help here, when there is an open hierarchy

of classes implementing the Shape interface.

DrLaszloJamfa at 2007-7-21 19:49:28 > top of Java-index,Java Essentials,Java Programming...