Backing Up Objects

H

Hal Vaughan

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
 
S

Stefan Ram

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

Lew

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

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.

Stefan said:
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.


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

Roedy Green

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

Piotr Kobzda

Lew said:
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 immutable:

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


piotr
 
P

Piotr Kobzda

Lew said:
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; }
}


piotr
 
L

Lew

Piotr said:
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.
 
H

Hal Vaughan

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

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.)
 
T

Twisted

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

Hal Vaughan

Twisted said:
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.

Thank you!

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

Hal
 
P

Piotr Kobzda

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


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


piotr
 
T

Twisted

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

Lew

Hal said:
Thank you!

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

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

Piotr Kobzda

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

Hal Vaughan

Lew said:
You will probably find Stefan's advice (the very first answer to your
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:

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.

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
 
T

Twisted

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

Hal Vaughan

Twisted said:
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.

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

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();
}

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

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
 
L

Lew

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

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

Hal Vaughan

Lew said:

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
 
L

Lew

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 );
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top