Java Forum / General / May 2007
Creating A Copy
Jason Cavett - 01 May 2007 20:13 GMT I want to create a copy of a set of data (so I can manipulate it, etc without affectnig any of the original data). Currently, I am using a deep copy that I discovered online. The problem with the deep copy is that it creates copies of EVERYTHING - listeners, etc, etc. This means that there's a whole lot of crap that has to be serializable. I would rather just make a copy of the data (parent class and its children).
How would I go about creating a new object with the same data, but the data is not a reference but an actual copy?
Thanks
Tom Hawtin - 01 May 2007 20:20 GMT > I want to create a copy of a set of data (so I can manipulate it, etc > without affectnig any of the original data). Currently, I am using a [quoted text clipped - 3 lines] > would rather just make a copy of the data (parent class and its > children). You can make the fields you are not interested in transient.
> How would I go about creating a new object with the same data, but the > data is not a reference but an actual copy? It's fairly easy to write a method that creates a copy of an object (well, it gets more complicated if you can have cycles). For example:
public final class MyClass { // @NonNull private SomeClass data; private MyClass(MyClass orig) { this.data = orig.data.copy(); } public MyClass copy() { return new MyClass(this); } ... }
Tom Hawtin
Jason Cavett - 01 May 2007 20:37 GMT > > I want to create a copy of a set of data (so I can manipulate it, etc > > without affectnig any of the original data). Currently, I am using a [quoted text clipped - 26 lines] > > Tom Hawtin Where does Cloneable come into play here? I just made my parent class implement Cloneable, used the Object.clone() method, and...well...frankly...everything appears to have worked correctly. I haven't tested all of this yet, but I'm doing that right now.
Also, if something is Cloneable, it doesn't need to be Serializable, does it? (Does cloning rely on that?)
Tom Hawtin - 01 May 2007 20:55 GMT > Where does Cloneable come into play here? I just made my parent class > implement Cloneable, used the Object.clone() method, > and...well...frankly...everything appears to have worked correctly. I > haven't tested all of this yet, but I'm doing that right now. Cloneable is evil. It just does a naive 'bitwise' copy.
> Also, if something is Cloneable, it doesn't need to be Serializable, > does it? (Does cloning rely on that?) Cloneable and Serializable are entirely independent.
Tom Hawtin
Jason Cavett - 01 May 2007 21:02 GMT > > Where does Cloneable come into play here? I just made my parent class > > implement Cloneable, used the Object.clone() method, [quoted text clipped - 9 lines] > > Tom Hawtin It's evil? But...it seems to work so well. Haha.
And a "naive bitwise copy" - can you explain a bit more? (In the meantime, I'll look it up online.)
Mark Rafn - 01 May 2007 21:54 GMT >I want to create a copy of a set of data (so I can manipulate it, etc >without affectnig any of the original data). Ok, so implement a copy constructor, a copyOf() method, or some other way to create the copy. For simple objects, the clone() method can work, but it's been abused a lot and does the wrong thing for many objects, so many are rightly suspicious of it.
The thing that people get wrong ALL THE TIME when discussing this is to think that "copy" is a well-defined term which should have exactly one implementation. NO! Each class has specific requirements about what its data means, and how (and whether) it should be copied.
>Currently, I am using a deep copy that I discovered online. The problem >with the deep copy is that it creates copies of EVERYTHING - listeners, etc, >etc. This means that there's a whole lot of crap that has to be serializable. To rephrase, "the problem with a deep copy is that I don't want a deep copy". You'll have the opposite problem with a shallow copy. You want a copy that knows which members should be copied and which should themselves have a duplicate instance created, and how to create those duplicates.
So write it.
>How would I go about creating a new object with the same data, but the >data is not a reference but an actual copy? Write code to do it. There's no magic except in your brain that knows which members should be copied, reused, or set to null. -- Mark Rafn dagon@dagon.net <http://www.dagon.net/>
Jason Cavett - 02 May 2007 13:46 GMT > >I want to create a copy of a set of data (so I can manipulate it, etc > >without affectnig any of the original data). [quoted text clipped - 27 lines] > -- > Mark Rafn d...@dagon.net <http://www.dagon.net/> Okay. Good point. The thing is, cloning seems to work.
I'll try creating a copy [constructor|method|something] and see how that works.
Thanks
Jason Cavett - 02 May 2007 14:07 GMT > > >I want to create a copy of a set of data (so I can manipulate it, etc > > >without affectnig any of the original data). [quoted text clipped - 36 lines] > > - Show quoted text - Meh. I just realized why I didn't do this in the first place.
I need to be able to copy generically (aka, I know the superclass type, but I won't necessarily know the subclass type at runtime). The superclass is a hierarchy of itself (type-wise). So, I know the parent, children and basic parameters. The problem is that I don't know specifics about any of those.
Maybe I didn't get enough sleep last night, but I'm stumped.
Jason Cavett - 02 May 2007 15:30 GMT > > > >I want to create a copy of a set of data (so I can manipulate it, etc > > > >without affectnig any of the original data). [quoted text clipped - 48 lines] > > - Show quoted text - The other issue I'm having is that, what I am copying, is a tree-type structure. Originally I was using Serialization (and Input/Output streams) to perform the copy. This didn't work when I used an object (not one that I created) that was not Serializable. That's why I started looking for other alternatives.
Yes, I *could* hard-code in the copy. That is a solution, but considering how many objects this tree-structure can hold, it really doesn't scale very well and doesn't make a whole lot of sense.
This is where I get stuck. It would be great if there was a way to ignore certain things in the Serialization copy and keep others. But, I haven't yet been able to figure out a way to do this. Do you have any suggestions?
Thanks
Lew - 02 May 2007 15:56 GMT > Yes, I *could* hard-code in the copy. That is a solution, but And should.
> considering how many objects this tree-structure can hold, it really > doesn't scale very well and doesn't make a whole lot of sense. Declare an overridable copy( T ) method in the supertype for the nodes. There is such a supertype, right? An interface?
Perhaps you can use clone() in an abstract superclass implementation, so that it will work for cases where it will work, no need to override. If a subclass can't use clone() effectively, write a detailed implementation for that class.
> This is where I get stuck. It would be great if there was a way to > ignore certain things in the Serialization copy and keep others. But, > I haven't yet been able to figure out a way to do this. Do you have > any suggestions? No serialization needed with a copy( T ).
I don't think there's any real magic bullet that gets you out of writing code here. It is logical for a type to know how to copy itself, so it's code well worth writing.
 Signature Lew
Jason Cavett - 02 May 2007 16:18 GMT > > Yes, I *could* hard-code in the copy. That is a solution, but > [quoted text clipped - 23 lines] > -- > Lew Yeah, I have an abstract supertype.
The point that was confusing me is that the object I'm copying is a tree-like structure (and, is, in fact the bases for a JTree). So, I need to worry about recursion, etc.
Alright, I'll give it a shot.
(As for the magic bullet - serialization actually works great. The only problem is, one of the objects in one class is not Serializable and it's not my class, so I can't change that. Sooo...that was end of that.)
Lew - 02 May 2007 18:54 GMT > (As for the magic bullet - serialization actually works great. The > only problem is, one of the objects in one class is not Serializable > and it's not my class, so I can't change that. Sooo...that was end of > that.) You can still serialize the object.
Let us say you have a class Foo with a member Baz that you don't control.
public class Foo { transient private Baz baz; ... }
Making the Baz element transient simply means you have to manually serialize and deserialize the Baz object. The fact that Baz is not Serializable is moot; no one is using Baz to try. That could be complicated if Baz is a collection itself, but let's assume it's some sort of fairly uncomplicated class with serializable attributes.
<http://java.sun.com/javase/6/docs/api/java/io/Serializable.html> explains to use
private void writeObject(java.io.ObjectOutputStream out) throws IOException; and
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
You write these methods to [de]serialize the well-known parts of Baz (untried, untested):
private void writeObject(java.io.ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeObject( baz.getIntegerValue() ); out.writeObject( baz.getStringValue() ); }
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); baz.setIntegerValue( (Integer) in.readObject() ); baz.setStringValue( (String) in.readObject() ); }
Then it matters not that Baz is not Serializable.
 Signature Lew
Mark Rafn - 02 May 2007 21:46 GMT >The point that was confusing me is that the object I'm copying is a >tree-like structure (and, is, in fact the bases for a JTree). So, I >need to worry about recursion, etc. Fairly easy, as long as each type knows how to copy itself. It gets tricky when you have cycles in your reference graph, as you need to track copying objects and references to objects separately. It's here that serialization starts to look tempting.
>(As for the magic bullet - serialization actually works great. The >only problem is, one of the objects in one class is not Serializable >and it's not my class, so I can't change that. Sooo...that was end of >that.) No, you just need to make it transient and implement a readObject and writeObject method that properly handles saving and restoring it (if needed). -- Mark Rafn dagon@dagon.net <http://www.dagon.net/>
Jason Cavett - 03 May 2007 15:46 GMT > >The point that was confusing me is that the object I'm copying is a > >tree-like structure (and, is, in fact the bases for a JTree). So, I [quoted text clipped - 14 lines] > -- > Mark Rafn d...@dagon.net <http://www.dagon.net/> Thanks for all the answers. I appreciate all your help and your expertise on the subject. This is new ground for me, so any explanation is helpful.
If I don't care about copying certain parts, can I just make that field transient and not worry about it? I'm not sure how well that'll work, but I tried to copy just the data as you suggested (by having each class know how to copy itself), but I had *major* problems doing this. (The whole tree structure really seems to mess things up.) Serialization was working before. That one object was not serializable, so that's why I couldn't continue to use it. So, is it possible to just completely ignore that object?
Hendrik Maryns - 03 May 2007 16:49 GMT Jason Cavett schreef:
>>> The point that was confusing me is that the object I'm copying is a >>> tree-like structure (and, is, in fact the bases for a JTree). So, I [quoted text clipped - 25 lines] > serializable, so that's why I couldn't continue to use it. So, is it > possible to just completely ignore that object? ‘transient’ has only a meaning if you use serialization to copy the objects. However, that is not what serialization was designed for.
As a lot of people have suggested by now: the semantics of copying is depends on the object to be copied. Since we know nothing about what you exactly want to do with your tree-like structure, the only suggestion we can give is: implement it yourself. That is, if you want to use the clone() method, implement it (preferably by invoking super.clone() as first statement, and then doing stuff with that).
H.
- -- Hendrik Maryns http://tcl.sfs.uni-tuebingen.de/~hendrik/ ================== http://aouw.org Ask smart questions, get good answers: http://www.catb.org/~esr/faqs/smart-questions.html
Mark Rafn - 03 May 2007 17:08 GMT >> >(As for the magic bullet - serialization actually works great. The >> >only problem is, one of the objects in one class is not Serializable >> >and it's not my class, so I can't change that. Sooo...that was end of >> >that.)
>> No, you just need to make it transient and implement a readObject and >> writeObject method that properly handles saving and restoring it (if needed).
>If I don't care about copying certain parts, can I just make that >field transient and not worry about it? Yes, but be aware that it will be null when deserialized, so you have to deal with setting it somehow if it's important. If it's not important, you should just remove it entirely from your object :) -- Mark Rafn dagon@dagon.net <http://www.dagon.net/>
Jason Cavett - 03 May 2007 17:53 GMT > >> >(As for the magic bullet - serialization actually works great. The > >> >only problem is, one of the objects in one class is not Serializable [quoted text clipped - 11 lines] > -- > Mark Rafn d...@dagon.net <http://www.dagon.net/> Okay, I was reading that as one of the problems. Unfortunately, the issue that was happening was that, when I was serializing the object, it serializes EVERYTHING (listeners, observers and their observers, etc.) so things were being serialized that I don't really care about with respect to this object (some of those listeners and observers need to stay, though - just not all of them). Specifically, there are two fields that I could ignore via transient. I did, and everything appears to be working correctly.
It's times like these I wish I had someone to help review my design, but, when you work in a small group and there aren't many (any) other programmers around, it's hard to bounce ideas off people. I appreciate your feedback, though. Thanks again.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|