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 / First Aid / August 2006

Tip: Looking for answers? Try searching our database.

Cloning and Distinct Copies of Objects

Thread view: 
Hal Vaughan - 15 Aug 2006 07:22 GMT
What is the difference between doing this with two string arrays:

newCopy = oldCopy;

instead of

newCopy = oldCopy.clone();
(including casting it if needed)

Am I wrong in understanding that the first way will create a distinctly
separate object and after doing it, changes to oldCopy are not copied over
to newCopy?  What is the need for the clone() method?

Thanks!

Hal
Eric Sosman - 15 Aug 2006 13:06 GMT
> What is the difference between doing this with two string arrays:
>
[quoted text clipped - 8 lines]
> separate object and after doing it, changes to oldCopy are not copied over
> to newCopy?

    "Yes."  That is to say, you are wrong.  Let's flesh out
the first example with a little more context:

    String[] oldCopy = { "Duke", "rulez!" };
    String[] newCopy = oldCopy;
    newCopy[0] = "Elvis";
    System.out.println(oldCopy[0] + " " + oldCopy[1]);

    The first line creates three objects: two String objects
and one array object.  There are also three references to those
objects: oldCopy is a reference to the array object, and the
elements in the array object are references to the String
objects.

    The second line declares the variable newCopy, and says
that it can hold a reference to an array object.  What array
object does it refer to?  The same one oldCopy refers to: the
value of oldCopy is copied to newCopy, so the two have the
same value and refer to the same array object.

    The third and fourth lines are a short experiment to
illustrate the outcome.  By now you should be able to predict
the output; I encourage you to do so and then to test your
prediction by running the code.

> What is the need for the clone() method?

    No "need" that I can see, but I do not see everything.
If we continue the fleshed-out example with

    String[] newClone = (String[])oldCopy.clone();

the effect is to create a brand-new array object and point
newClone at it.  The new array object is a duplicate of the
old in the sense that it has the same length and all its
elements have the same values, so in this case there's a
second two-element array whose elements in turn refer to
the two Strings "Elvis" and "rulez!".  (They're the same
two Strings the original array refers to, by the way: the
array elements were copied, and they are references to the
existing String objects.  Nothing has happened to those
String objects; there's just a few more references aiming
at them than there used to be.)

    If you have a background in C or C++ it may be helpful
to think of references as "pointers" to object instances
that live "on the heap."  It is often said that Java does
not have pointers, but I think that's a confusing way of
putting things.  Java's references *are* pointers in every
important sense, but Java does not allow you to do arithmetic
on those pointers, manufacture them from whole cloth, or
otherwise twiddle with their innards.  Copying a pointer in
C or C++ doesn't affect the pointed-to thing; copying a
reference in Java acts similarly.

Signature

Eric Sosman
esosman@acm-dot-org.invalid

Hal Vaughan - 15 Aug 2006 17:55 GMT
>> What is the difference between doing this with two string arrays:
>>
[quoted text clipped - 63 lines]
> C or C++ doesn't affect the pointed-to thing; copying a
> reference in Java acts similarly.

I don't know C or C++, but I've heard of pointers and read comments in
places about Java not having pointers.  I'm self taught (other than a VAX
11/780 Assembler class in the 1980s), so I find there's a lot of times that
I know some advanced concepts and miss things that I should know.

If I understand all this correctly, then if I want to duplicate a String[]
function, I need to do something like this:

String[] oldCopy = { "Duke", "rulez!" };
String[] newCopy = new String[oldCopy.length];
int i;
for (i = 1; i < oldCopy.length; i++) {
       newCopy[i] = oldCopy[i].clone();
}

Is that right?  Since I can create a new array that will still reference the
old strings, it seems that the only way to create a complete copy as it is,
as an independent object to save the exact state of oldCopy is to clone
each String individually.

Hal
Eric Sosman - 15 Aug 2006 19:18 GMT
Hal Vaughan wrote On 08/15/06 12:55,:
> [...]
> If I understand all this correctly, then if I want to duplicate a String[]
[quoted text clipped - 4 lines]
> int i;
> for (i = 1; i < oldCopy.length; i++) {

   ITYM 0 instead of 1 here.

>         newCopy[i] = oldCopy[i].clone();

   This won't work for at least three reasons, one of them
fixable and the other two inescapable (to the best of my
knowledge).

   The fixable problem is that clone() returns an Object
reference but you need a String reference, so the statement
won't compile.  You could add a (String) cast to solve that
problem; the compiler would insert code to do a run-time check
that the Object is in truth a String, and then either allow
the assignment or throw ClassCastException.

   The first inescapable problem is that the clone() method
of String is protected, meaning that it's accessible only
from within the String class itself, from within other classes
of the java.lang package, or from subclasses of String.  Since
your code is not part of String nor part of java.lang, and
since String is final and can have no subclasses, your code
cannot call String's clone() method.

   The second inescapable problem is that even if you somehow
managed to call clone() on a String, you would find that the
String class does not implement the Cloneable interface.  The
clone() method (whose implementation String inherits from
Object) will just throw a CloneNotSupportedException and
snicker at you behind your back.

   The upshot: You can't clone a String -- and String is not
unique in being non-cloneable, either.

> [...] Since I can create a new array that will still reference the
> old strings, it seems that the only way to create a complete copy as it is,
> as an independent object to save the exact state of oldCopy is to clone
> each String individually.

   You could *copy* (not *clone*) the String objects by using
String's copy constructor, or by a few other routes.  But it's
a dumb thing to do: Why do you think you need all those copies?
Keep in mind that a String is immutable; once it's been created
its content cannot change.  If the String eventually expires,
it will have its original value right up to the instant when
the garbage collector swings its scythe.  (Well, somebody once
posted a horrible hack that showed how a String could in fact
be changed -- but if *that* sort of mischief is afoot in your
JVM, you might as well throw in the towel.)

   Do you clone yourself when you tell someone your name?  Do
you give away cloned copies, or do you let the other people
access the one and only You through a reference?

Signature

Eric.Sosman@sun.com

Hal Vaughan - 15 Aug 2006 19:40 GMT
> Hal Vaughan wrote On 08/15/06 12:55,:
>> [...]
[quoted text clipped - 54 lines]
> be changed -- but if *that* sort of mischief is afoot in your
> JVM, you might as well throw in the towel.)

I'm using a "restore to last saved" option in the menu so if someone makes
mistakes, they can revert to the last saved data.  I need to store several
String[] structures as they are when the data is saved so they can be used
later if needed.

Hal
Eric Sosman - 15 Aug 2006 20:38 GMT
Hal Vaughan wrote On 08/15/06 14:40,:

>>    You could *copy* (not *clone*) the String objects by using
>>String's copy constructor, or by a few other routes.  But it's
[quoted text clipped - 4 lines]
> String[] structures as they are when the data is saved so they can be used
> later if needed.

   You may need a copy of the String[], which is an array of
references to String objects, but there's no need to make copies
of the String objects those references point to.

   Here's the original array, before anybody edits anything:

    oldarray[0] -> "Duke"
    oldarray[1] -> "rulez!"

Now make a new copy of the array and the references it contains,
which point to the original String objects:

    oldarray[0] -> "Duke"   <- newarray[0]
    oldarray[1] -> "rulez!" <- newarray[1]

Now edit the new array, changing one of its references to point
to a different String:

    oldarray[0] -> "Duke"      newarray[0] -> "Elvis"
    oldarray[1] -> "rulez!" <- newarray[1]

There is no need for extra copies of "rulez!" or of "Duke".
All the String objects are still alive, still referred to,
still hanging on to their immutable content.  If you want
to commit the edit, keep newarray and let oldarray drop on
the floor.  If you want to revert, keep oldarray and abandon
newarray to the garbage collector.

   I think the distinction between an object reference and
an object instance is not yet quite clear to you.  When the
light eventually dawns, things will make sense quite suddenly.

   Objects are telephones; references are telephone numbers.
If you want to get calls from a hundred people, give out a
hundred copies of your telephone number -- a hundred copies
of the reference value -- but don't burden yourself by trying
to carry a hundred phones on your belt.

Signature

Eric.Sosman@sun.com

Patricia Shanahan - 15 Aug 2006 19:43 GMT
....
> I don't know C or C++, but I've heard of pointers and read comments in
> places about Java not having pointers.  I'm self taught (other than a VAX
> 11/780 Assembler class in the 1980s), so I find there's a lot of times that
> I know some advanced concepts and miss things that I should know.

Java does have pointers, though they are called "references". It lacks a
lot of dangerous baggage that C added to the concept of "pointer", such
as pointer arithmetic, conversion between pointer and integer types, and
unchecked pointer conversions. Java forces its references to either be
null or point to an object of appropriate class.

Because a lot of programmers learned about pointers in connection with
C, some writers about Java try to avoid the word, on the theory that
anyone learning Java would be too dumb to understand that Java pointers
just point to objects, and don't do anything else.

> If I understand all this correctly, then if I want to duplicate a String[]
> function, I need to do something like this:
[quoted text clipped - 10 lines]
> as an independent object to save the exact state of oldCopy is to clone
> each String individually.

String[] oldCopy = { "Duke", "rulez!" };
String[] newCopy = new String[oldCopy.length];
int i;
for (i = 1; i < oldCopy.length; i++) {
        newCopy[i] = new String(oldCopy[i]);
}

but there are VERY few situations in which you need anything like that.

Why do you want to avoid sharing String objects?

Patricia
Hal Vaughan - 15 Aug 2006 20:00 GMT
> ....
>> I don't know C or C++, but I've heard of pointers and read comments in
[quoted text clipped - 40 lines]
>
> Patricia

I want a backup of the object at a particular time so the user can revert to
the last saved state if desired, so I need to be able to copy the object
and make sure the copy doesn't have the new changes made after the copy is
done.

Hal
Patricia Shanahan - 15 Aug 2006 21:20 GMT
...
>> Why do you want to avoid sharing String objects?
>>
[quoted text clipped - 4 lines]
> and make sure the copy doesn't have the new changes made after the copy is
> done.

You need to make sure the object your backup references does not have
any changes made after the backup was done. Copying is only a means to
that end.

You can divide objects, for this purpose, into two categories, mutable
and immutable.

An immutable object has no methods that change its own state. For an
immutable object, such as a String, you only need to copy the reference.
String is not Cloneable because you don't need to copy it for this sort
of situation.

The state of a mutable object can change, so to be sure of getting back
to an earlier state you need a copy of the object, not just a reference.

Patricia


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



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