Backing Up Objects

H

Hal Vaughan

Lew said:
Hal said:
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.

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
 
T

Twisted

Hal said:
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 );

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

Hal Vaughan

Twisted said:
Hal said:
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 );

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.

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
 
H

Hal Vaughan

Hal Vaughan wrote:
....
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top