Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / July 2007

Tip: Looking for answers? Try searching our database.

Backing Up Objects

Thread view: 
Hal Vaughan - 09 Jul 2007 06:38 GMT
This seems to me to be an issue in dealing with pointers and cloning
objects.  I understand that if I have two Objects, whether they're
something like a String or an object I define myself, then when I do:

String newString = oldString;

that newString is simply a pointer to oldString so if I change the value in
one, I change the value in the other.

What I'd like to do is copy an object I've created that has a few HashMaps
in it to an entirely new object and make sure they are both separate.
Whenever the data in this program is saved, a backup copy of this object
would be created.  That way, while I'm editing data in the program, if I
make a mistake, I can easily restore things to the last time I saved by
copying the back up object to the new object.

This object is essentially a data table and I have several of them, stored
in a Vector.  I've read that if I use clone() on a Vector, that a new
Vector is created, but the new one will still point to all the same objects
in the first Vector.  If I iterate through the Vector and clone each Object
in it and store each cloned object in a new Vector, will that new Vector
have a copy of equivalent values without them being the same objects?  

If that doesn't work, how can I create a backup of an Object so I can change
the values in one while the values in the other stay the same?

Thanks!

Hal
Stefan Ram - 09 Jul 2007 11:11 GMT
>String newString = oldString;

 If this is compilable, then »oldString« is the a name of a
 variable that contains a reference value. When this is
 executed, the other variable (named »newString«) will contain
 a copy of this reference value. But no object will be
 altered in the course of this action.

>how can I create a backup of an Object

 This depends on the circumstances. There are »shallow« copies
 only copying the fields and »deep« copies, where the fields
 are altered to refer to copies of subobjects (recursively),
 and there are mixtures. Only you can know, what is appropriate
 for your requirements. By this knowledge, you can implement
 the operation as a method.

 Means to copy often are a »copy constructor« or the method »clone«.
 You might look up these subjects in the technical literature.
Lew - 09 Jul 2007 13:25 GMT
Hal Vaughan writes:
> String newString = oldString;
>
> that newString is simply a pointer to oldString so if I change the value in
> one, I change the value in the other.

Ironically, under most circumstances it is not possible to change the value of
a String, so this made a bad example.  Strings are "immutable"; without
resorting to evil reflection trickery their value cannot be changed after
construction.  An example using "Foo" instead of "String" would be valid (one
would assume Foo is not immutable).  However, the main point of the post is
valid, that assignment copies references, not objects.

>> how can I create a backup of an Object

>   This depends on the circumstances. There are »shallow« copies
>   only copying the fields and »deep« copies, where the fields
[quoted text clipped - 5 lines]
>   Means to copy often are a »copy constructor« or the method »clone«.
>   You might look up these subjects in the technical literature.

Hal Vaughan writes:
>> This object is essentially a data table and I have several of them, stored
>> in a Vector.  I've read that if I use clone() on a Vector, that a new

Why did you use the senescent Vector class in lieu of, say, ArrayList or any
other List (or more generic Collection) class?  Vector is, what, seven or
eight years out of date, and dangerous?  If you need synchronized methods,
Collections.synchronizedList( yourList ) is much safer than Vector.

Signature

Lew

Piotr Kobzda - 09 Jul 2007 21:31 GMT
> Hal Vaughan writes:
>> String newString = oldString;
[quoted text clipped - 8 lines]
> changed after construction.  An example using "Foo" instead of "String"
> would be valid (one would assume Foo is not immutable).

One would assume "String" is immutable:

  public class String {
    public java.lang.String value;
    public String toString() { return value; }
  }

piotr
Piotr Kobzda - 09 Jul 2007 21:35 GMT
> Hal Vaughan writes:
>> String newString = oldString;
[quoted text clipped - 8 lines]
> changed after construction.  An example using "Foo" instead of "String"
> would be valid (one would assume Foo is not immutable).

One would assume "String" is mutable:

  public class String {
    public java.lang.String value;
    public java.lang.String toString() { return value; }
  }

piotr
Lew - 10 Jul 2007 00:53 GMT
Hal Vaughan writes:
>>> String newString = oldString;
>>>
>>> that newString is simply a pointer to oldString so if I change the
>>> value in
>>> one, I change the value in the other.

Lew wrote:
>> Ironically, under most circumstances it is not possible to change the
>> value of a String, so this made a bad example.  Strings are
>> "immutable"; without resorting to evil reflection trickery their value
>> cannot be changed after construction.  An example using "Foo" instead
>> of "String" would be valid (one would assume Foo is not immutable).

> One would assume "String" is mutable:
>
>   public class String {
>     public java.lang.String value;
>     public java.lang.String toString() { return value; }
>   }

You're just being argumentative.

Absent any specific disclaimer to the contrary, as the original post was, why
in the world would one figure that "String" meant anything other than
"java.lang.String"?  If you wish to assume the OP is an idiot who reuses the
most fundamental class names, thus damaging maintenance, then perhaps, and
only perhaps, your point would have a micro-skootch of merit, but I refuse to
believe the OP was that stupid.

Be real.

Signature

Lew

Hal Vaughan - 10 Jul 2007 02:03 GMT
> Hal Vaughan writes:
>>>> String newString = oldString;
[quoted text clipped - 27 lines]
>
> Be real.

I may be self taught and, because of that, have missed quite a few of the
basics (like the issue about others lists being better than vectors), but I
can assure you the OP is NOT that stupid.

Dense and stubborn, maybe, but not that stupid.

Hal
(The O.P.)
Piotr Kobzda - 10 Jul 2007 09:29 GMT
> Hal Vaughan writes:
>>>> String newString = oldString;
[quoted text clipped - 19 lines]
>
> You're just being argumentative.

No, I'm not.  My apologies to all of you who have interpreted my post
that way.  That was just to show that there is other possibility (other
than reflection mentioned by you) to mutate "String" value, which gives
the above example similar sense as using Foo does.  That's all.

> Absent any specific disclaimer to the contrary, as the original post
> was, why in the world would one figure that "String" meant anything
> other than "java.lang.String"?  If you wish to assume the OP is an idiot
> who reuses the most fundamental class names, thus damaging maintenance,
> then perhaps, and only perhaps, your point would have a micro-skootch of
> merit, but I refuse to believe the OP was that stupid.

I have never assumed that.  If the OP thinks I did, my apologies to him,
that was not my intent.

> Be real.

Well, I'll try.  Thank you for advice.

piotr
Twisted - 10 Jul 2007 12:07 GMT
> No, I'm not.  My apologies to all of you who have interpreted my post
> that way.  That was just to show that there is other possibility (other
> than reflection mentioned by you) to mutate "String" value, which gives
> the above example similar sense as using Foo does.  That's all.

Of course, it doesn't *really* mutate a "String" value, in that your
String is seen by the compiler as a different type to, and not
assignable to, java.lang.String.

On the other hand, there is another real way to mutate a String --
alter it when it's serialized, then deserialize it.
Piotr Kobzda - 10 Jul 2007 13:25 GMT
> Of course, it doesn't *really* mutate a "String" value, in that your
> String is seen by the compiler as a different type to, and not
> assignable to, java.lang.String.

Of course, my String is different type.  It simply allows to implement
the scenario described by the OP:

<sscce>
public class Test {
    public static void m(String[] args) {
        class String {
            java.lang.String value;
            public java.lang.String toString() { return value; }
        }
        String oldString = new String();
        String newString = oldString;  // the OP's line (literally)
        oldString.value = "123";
        System.out.println(newString);
    }
}
</sscce>

> On the other hand, there is another real way to mutate a String --
> alter it when it's serialized, then deserialize it.

That way you cannot mutate the value of an existing String object.  It
allows to create a new one only.  To achieve similar effect, much easier
is to use a String's "copy constructor".

piotr
Roedy Green - 09 Jul 2007 20:13 GMT
On Mon, 09 Jul 2007 01:38:13 -0400, Hal Vaughan
<hal@thresholddigital.com> wrote, quoted or indirectly quoted someone
who said :

>String newString = oldString;
>
>that newString is simply a pointer to oldString so if I change the value in
>one, I change the value in the other.

No.  All you can do is make newString point to a different string.
OldString and all the references pointing to it are the same.

What you are describing is a char[].

If you change it, it changes for all references pointing to it.
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
Twisted - 10 Jul 2007 04:38 GMT
OK, it's high time *someone* answered the OP's question here.

If you want to do a full deep copy of a data structure, just serialize
and deserialize it. If you want to, to a RAM buffer rather than a
(possibly temporary) disk file. (The TCP/IP loopback interface is
another intriguing possibility.) As an added bonus feature, if you
serialize to a .bak file on disk you get a disk backup that can be
restored later by deserializing it, e.g. after a program abend.

You need to make the stuff you use in this data structure
serializable. The standard collection classes already are
serializable. The Java Tutorial on Sun's Web site has further
information about serialization for beginners.
Hal Vaughan - 10 Jul 2007 06:34 GMT
> OK, it's high time *someone* answered the OP's question here.
>
[quoted text clipped - 9 lines]
> serializable. The Java Tutorial on Sun's Web site has further
> information about serialization for beginners.

Thank you!

Now I have some good terms to use for searching.  I can work it out from
there.

Hal
Lew - 10 Jul 2007 12:28 GMT
>> OK, it's high time *someone* answered the OP's question here.
>>
[quoted text clipped - 14 lines]
> Now I have some good terms to use for searching.  I can work it out from
> there.

You will probably find Stefan's advice (the very first answer to your post)
more manageable.  Serialization is a topic fraught with perils.

Stefan Ram suggested:
>   This depends on the circumstances. There are »shallow« copies
>   only copying the fields and »deep« copies, where the fields
[quoted text clipped - 5 lines]
>   Means to copy often are a »copy constructor« or the method »clone«.
>   You might look up these subjects in the technical literature.

The usual best is to write your own copy method(s).

Serialization requires a number of steps to ensure safety, covered well by
Joshua Bloch's /Effective Java/.  You need a serialVersionUID, possibly to
write methods writeObject(), readObject(), readObjectNoData(), writeReplace()
and readResolve(), making certain fields transient, making sure all referenced
objects are also serializable, more threading concerns, possible static
variable trouble, and so on.  It creates a back-door constructor and a public
access to the class that must be maintained in perpetuity.

Just writing a copy method is likely to be much easier.

Signature

Lew

Hal Vaughan - 10 Jul 2007 17:21 GMT
>>> OK, it's high time *someone* answered the OP's question here.
>>>
[quoted text clipped - 18 lines]
> post)
> more manageable.  Serialization is a topic fraught with perils.

I think I got confused at one point.  I was listening to advice from a
friend who seemed skeptical of that.  Thanks for pointing that out.  (And
I'll point it out to my friend!)

> Stefan Ram suggested:
>>   This depends on the circumstances. There are »shallow« copies
[quoted text clipped - 17 lines]
> variable trouble, and so on.  It creates a back-door constructor and a
> public access to the class that must be maintained in perpetuity.

Perpetuity is one thing I'm not concerned about.  All I'm doing is storing,
in RAM, a copy of what I've been working with until I either save it again
(in which case I need a new copy for backup) or until I exit the program.

> Just writing a copy method is likely to be much easier.

But if I'm writing a copy method, I have to write something that will take
each Object I have in my class and duplicate it, which leads back to the
original problem: How do I make an actual copy of an object?  Are there
types of Objects where clone() does an actual clone and create a new
Object?

Thanks!

Hal
Twisted - 10 Jul 2007 20:33 GMT
> But if I'm writing a copy method, I have to write something that will take
> each Object I have in my class and duplicate it, which leads back to the
> original problem: How do I make an actual copy of an object?  Are there
> types of Objects where clone() does an actual clone and create a new
> Object?

If you're just copying, say, an ArrayList of Foos where Foos are some
simple value objects that implement Cloneable, you can use a custom
copying method to do it easily.

If you've got a substantially more complex data structure which would
have a nontrivial traversal algorithm and contains an open-ended
variety of things, you're probably going to have a much easier time
using serialization. That takes the matter of writing the traversal
algorithm and getting it right out of your hands and leaves you
without much more to do for most of your classes than Cloneable. With
Cloneable you need to tack on "implements Cloneable" and include

public Object clone () {
   super.clone();
}

to make "clone" public, at minimum. And you've still introduced a
"backdoor constructor" of sorts.

Serializability in a lot of cases just means tacking on "implements
java.io.Serializable" and including
private static final long serialVersionUID = 1;

and increasing this by one every time you make certain changes to the
class in question (basically any change where there was a non-
transient field with a particular name and there no longer is or a
field changes type other than to a supertype of the old type, and any
change where a non-transient field starts existing and cannot be null,
false, or zero by default). More complex stuff is only infrequently
needed, e.g. a singleton should have every field transient and a
readResolve method that returns the singleton instance from a static
field if for some reason it's serializable. (A singleton value object
such as a Null or a NaN or an Infinity, for example, which is a
subclass of some more general value type class.)
Hal Vaughan - 12 Jul 2007 10:40 GMT
>> But if I'm writing a copy method, I have to write something that will
>> take each Object I have in my class and duplicate it, which leads back to
[quoted text clipped - 6 lines]
> simple value objects that implement Cloneable, you can use a custom
> copying method to do it easily.

In the long run, the data comes down to Strings.  While I have my own class
that stores them, the bottom line is I'm storing Strings that I need to
copy.

> If you've got a substantially more complex data structure which would
> have a nontrivial traversal algorithm and contains an open-ended
[quoted text clipped - 3 lines]
> without much more to do for most of your classes than Cloneable. With
> Cloneable you need to tack on "implements Cloneable" and include

So if it's at all complex, I'm better using serialization?  If so, there's
one aspect to this I'm not sure of.  I don't want to write the objects to
anything.  I'm only storing them within the program temporarily, either
until the next save or until the program ends.  From what I saw, using
serialization means writing the data to a stream.  Can that stream go to an
object and be read back from that object later?  (Instead of a stream being
written to a file on the drive or through a network connection?)

> public Object clone () {
>     super.clone();
[quoted text clipped - 18 lines]
> such as a Null or a NaN or an Infinity, for example, which is a
> subclass of some more general value type class.)

I'm not worried about changes, since any data written from one of my
serializable objects would only be stored in RAM and never on disk.  The
longest it would last would be until the program exits, so version tracking
is moot (unless I've missed something important).

Thanks!

Hal
Lew - 12 Jul 2007 15:14 GMT
> So if it's at all complex, I'm better using serialization?  If so, there's
> one aspect to this I'm not sure of.  I don't want to write the objects to
[quoted text clipped - 3 lines]
> object and be read back from that object later?  (Instead of a stream being
> written to a file on the drive or through a network connection?)

<http://java.sun.com/javase/6/docs/api/java/io/ByteArrayOutputStream.html>
<http://java.sun.com/javase/6/docs/api/java/io/ByteArrayInputStream.html>

I still prefer copy methods to serialization.

Signature

Lew

Hal Vaughan - 12 Jul 2007 15:36 GMT
>> So if it's at all complex, I'm better using serialization?  If so,
>> there's
[quoted text clipped - 10 lines]
>
> I still prefer copy methods to serialization.

Okay, so how do I make copy of a String so I can modify either the copy or
the original without effecting the other?  (Yes, I know Strings follow
different rules than other Objects, but this is a start.)

I'm not ruling copying out.  I am still finishing up some other stuff and
this is a few steps off for me.  I've learned to look ahead and ask
questions like this before I get to that part of my work so I have time to
get answers and explore what people tell me about.

Hal
Lew - 12 Jul 2007 23:57 GMT
> Okay, so how do I make copy of a String so I can modify either the copy or
> the original without effecting [sic] the other?  (Yes, I know Strings follow
> different rules than other Objects, but this is a start.)

As was pointed out a few times in this thread, you cannot modify a String's value.

Neither the copy nor the original.

You can copy a String a couple of ways, e.g.,
   String original = "Something";
   String copy = new String( original );

Signature

Lew

Hal Vaughan - 13 Jul 2007 03:04 GMT
>> Okay, so how do I make copy of a String so I can modify either the copy
>> or
[quoted text clipped - 5 lines]
>
> Neither the copy nor the original.

That was why I was asking.  While there are other objects involved, there
are a number of Strings involved.

> You can copy a String a couple of ways, e.g.,
>     String original = "Something";
>     String copy = new String( original );

Okay, I missed the obvious.  Thanks!

Hal
Twisted - 13 Jul 2007 03:06 GMT
> > Okay, so how do I make copy of a String so I can modify either the copy or
> > the original without effecting [sic] the other?  (Yes, I know Strings follow
[quoted text clipped - 7 lines]
>     String original = "Something";
>     String copy = new String( original );

And it's pointless. Strings are immutable. Better than copying them,
intern them all -- myString = myString.intern();

Now duplicate Strings don't waste extra memory.

Whenever you use String operations to "modify" a String you actually
make a mutated copy of the original String; if you have myString =
"foo" and then yourString = myString and then myString =
myString.append("bar") you end up with myString.equals("foobar")
(myString == "foobar" if you intern myString after the append) and
yourString == "foo". The old version is still preserved; yourString
did not change to "foobar". (Note that interned strings will compare
== to one another and to literals, which are automatically interned,
when they are equals(). Comparing interned strings can be especially
efficient then.)

Regardless, you can just copy the String references when you copy the
data structure, and the backup won't change spontaneously because of
edits to the original data structure, as long as you don't do anything
sneaky with reflection to mutate the Strings in the data structure.

If it's mainly Strings you can probably also find some sensible way to
externalize it with writeExternal and read it back with readExternal
in an ASCII-based (or unicode, anyway) format. This would be nicer
than serialization for this sort of data, and provides a way to both
save to disk and (via ByteArrayFooStreams or a temporary file) backup.

Some wag will no doubt now suggest externalizing as XML. XML seems to
be the current "hammer fad", which makes everything look like a nail
to some people.
Hal Vaughan - 13 Jul 2007 04:34 GMT
>> > Okay, so how do I make copy of a String so I can modify either the copy
>> > or
[quoted text clipped - 36 lines]
> than serialization for this sort of data, and provides a way to both
> save to disk and (via ByteArrayFooStreams or a temporary file) backup.

I'll be looking into this.  I've never heard of intern() or writeExternal().
That's more I can explore.

> Some wag will no doubt now suggest externalizing as XML. XML seems to
> be the current "hammer fad", which makes everything look like a nail
> to some people.

XML would be pointless.  I'm not saving the data for longer than the program
is running.  Personally I think XML is overused.

Hal
Hal Vaughan - 22 Jul 2007 08:36 GMT
...
> If that doesn't work, how can I create a backup of an Object so I can
> change the values in one while the values in the other stay the same?

Thanks to everyone for all the helpful replies.  I looked over everything
and tried a number of test setups, both to see what would work and to learn
more about Java in general.  Basically I was working with a class called
SedTable (the program is a setting editor, so some of the classes are
prefixed by Sed) and SedRow.  Within SedTable there was a Vector named
fullTable and each element was one SedRow.  Within SedRow I had another of
my own classes, StringHashMap (I'm avoiding generics and, for now, sticking
with what I can use in Java 1.4.2.)  I also had other data in each SedRow
class, such as a flag to show if a row had been deleted and other flags and
metadata.

First I looked at alternatives to Vectors since someone mentioned there were
issues with Vectors and they're outdated.  (I don't think thread safety is
a factor.  While this is a Swing interface, once a value is selected or
changed, the components are frozen until all the updates are done (which is
usually too fast for the user to detect).  I changed to using ArrayLists,
which took almost no coding change and made a few parts easier.  (That's
one issue to being self taught -- I learn about one thing that works and
don't know there are other structures that work even better.)

In the long run I decided to serialize the objects.  I know to some that
sounds like a lot of work and it seems preferred to just create copy
methods, but memory doesn't seem to be an issue from what I've measured and
it took far less code to serialize the objects than to copy them.

Basically I added a backup() method in SedTable that serializes the
ArrayList that contains all the SedRows.  Then I got an error for SedRow,
but all I had to add was "implements Serializable" to the class declaration
line.  While I was at it, I did the same to my StringHashMap (and
shift-ctrl-o fixed the imports in Eclipse).  Then it only took a few lines
of code to output the object to an OjbectOutPutStream, wrap a
ByteArrayOutputStream around it, and have it dump everything into a byte[].
To read it back, I just reversed it and read from the same byte[] with a
ByteArrayInputStream with an ObjectInputStream wrapped around it.

I figured if I was going to copy it, I'd have to write a loop in SedTable to
go through the ArrayList and call a copy method on each SedRow.  Then I'd
have to store the StringHashMaps and a few other objects in SedRow.  That
would be new code in at least 2 classes and extra code for several loops
and trying to create backup copies within classes.  Another factor, one I
didn't realize until I was trying to ride the code, was that people
suggested using a copy() constructor, but nobody mentioned how, when using
one, I could make sure the new class had new data and not just pointers to
the old data.  In the long run it was actually easier to serialize.  (Add 2
words to several classes and just add a few lines of I/O code to store each
ArrayList.)

I found this link extremely helpful in using the serialization:

http://java.sun.com/developer/technicalArticles/Programming/serialization/

I've already tested this and am thrilled with how easily it works.

Hal


Free Magazines

Get 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 ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.