duplication issue (newbie)

L

lallous

Hello,

I tried to use the clone() by letting my class implement clonable, however,
I don't want to guard my code whenever I duplicate my class.
The clone() must always succeed (why would it fail other than when there is
no memory to create a new instance)?

In worst cases one would create a new instance and do member copying to the
new instance:

class Class1 implements Clonable
{
public static class innerclass
{
// has duplicate method too
}

public Object clone()
{
private int x1;
try
{
return super.clone();
}
Catch (CloneNotSupportedException e)
{
Class1 newobj = new Class1();
newobj.x1 = x1;
return newobj;
}
}

public Class1 duplicate()
{
Class1 newentry = new Class1();
newentry.x1 = x1;
return newentry;
}
}

Now in Class2:

method()
{
Class1 c2, c1 = new Class1();

c2 = c1.clone(); // <-- cannot w/o casting from Object to Class1.

c2 = (Class1) c1.clone(); // works.

c2 = c1.duplicate(); // <-- works fine
}

Can someone tell me is the 'duplicate()' is safe, why should I use clone()
and not my own cloning code (same as C++ copy constructors)?
Does Object.clone() clones my private variables too in MyClass?
Is it safe to duplicate static inner classes using duplicate?
 
R

Ryan Stewart

lallous said:
Hello,

I tried to use the clone() by letting my class implement clonable, however,
I don't want to guard my code whenever I duplicate my class.
The clone() must always succeed (why would it fail other than when there is
no memory to create a new instance)?

In worst cases one would create a new instance and do member copying to the
new instance:
*snip nasty code*

Can someone tell me is the 'duplicate()' is safe, why should I use clone()
and not my own cloning code (same as C++ copy constructors)?
Does Object.clone() clones my private variables too in MyClass?
Is it safe to duplicate static inner classes using duplicate?

Why don't you try posting some actual compilable code? Instance variables go
at the class level, Cloneable is spelled like I just did, and keywords (like
catch, hint hint) start with lowercase letters. A minor point is that inner
classes are, by definition, not static.

Use clone() because it's the standard. Override it if you need to. See
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html for details on
how the method works. Basically, it creates a new instance of the given
class and initializes all its fields with the exact contents of the
original's fields. That means an int field will be set to the same int
value, a String field will *reference* the same String object, and a
StringBuffer field will reference the same StringBuffer object. It's this
last case (or any other case involving a mutable object) that you'd need to
override clone() with your own implementation, because if you change the
contents of the StringBuffer in the original object, you've also affected
the clone since they're pointing at the same object.
 
C

Chris Smith

lallous said:
I tried to use the clone() by letting my class implement clonable, however,
I don't want to guard my code whenever I duplicate my class.
The clone() must always succeed (why would it fail other than when there is
no memory to create a new instance)?

The clone() method could conceivably fail with OutOfMemoryError, yes.
However, that's not what CloneNotSupportedException is about. This
exception is there to catch your errors when you try to clone an object
that doesn't implement Cloneable. If you're sure that you don't do so
(meaning that it's an error in the code if you do) then by all means
feel free to catch the CloneNotSupportedException... but don't try an
alternate method of creating the clone() from that catch block!

Remember, if you get here, then something is seriously wrong with your
code. If that's the case, then you want your application to fail, not
plug along miserably until it messes up something.
public Class1 duplicate()
{
Class1 newentry = new Class1();
newentry.x1 = x1;
return newentry;
}
Can someone tell me is the 'duplicate()' is safe, why should I use clone()
and not my own cloning code (same as C++ copy constructors)?

Because duplicate() is broken, in exactly the same way that C++ copy
constructors are broken. Luckily, implicit use of C++ copy constructors
is generally confined to the stack where inheritance doesn't work anyway
-- and good C++ programmers know to be very careful when explicitly
calling a copy constructor when there are inheritance relationships
between the classes involved. Not so with Java's cloning: Java
developers expect clone() to work correctly, and your duplicate() method
fails their expectations.

Basically, clone() makes a guarantee that the class of the copy will be
the same as the class of the original. That only makes sense. However,
there's no way for anyone to extend your class with a duplicate()
method, and write a duplicate() method that returns the correct
instance.

Since your duplicate() method returns a Class1 instance, their Class1b
(extends Class1) duplicate could not use it, and all that copying code
would have to be repeated. But if it involves private fields that don't
have direct accessors and mutators, then is can *not* be repeated in the
subclass. Even if it could be repeated in a subclass, the subclass then
suddenly depends on the exact set of fields in the superclass... leading
to Fragile Subclass Syndrome, which is a very common medical cause of
headaches among programmers. Solving this conundrum is part of the
magic of Object.clone().

The other magic of Object.clone() is to provide a way to copy an object
without any side-effects of object creation. Again, avoiding Fragile
Subclass Syndrome, you want to make no assumptions about the bahavior of
a superclass. The constructor for a superclass might have unpredictable
side-effects that you can't reverse. You don't necessarily *need* the
constructor, since you plan to copy all the state from the old object
anyway. So clone() lets you create a new object without calling the
constructor. That's the other part of the clone() magic.

Incidentally, aside from those two pieces of clone() magic, Object's
implementation of clone() does exactly what your duplicate() does. You
are, however, responsible for finishing the job... any references to
other objects providing mutable state that is considered part of this
object's state need to be changed, by recursively calling clone() on
those sub-objects.

So that's cloning in a nutshell.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Tony Morris

A minor point is that inner
classes are, by definition, not static.

An inner class may or may not be, declared static.

--
Tony Morris
(BInfTech, Cert 3 I.T., SCJP[1.4], SCJD)
Software Engineer
IBM Australia - Tivoli Security Software
(2003 VTR1000F)
 
R

Ryan Stewart

Tony Morris said:
A minor point is that inner

An inner class may or may not be, declared static.

"An inner class is a nested class that is not explicitly or implicitly
declared
static. Inner classes may not declare static initializers (§8.7) or member
inter-faces.

Inner classes may not declare static members, unless they are compile-time

constant fields (§15.28)."

.... straight from the JLS 2.0.
 
K

Karl von Laudermann

lallous said:
Hello,

I tried to use the clone() by letting my class implement clonable, however,
I don't want to guard my code whenever I duplicate my class.

In this case, Sun recommends implementing clone() thusly:

public Object clone()
{
try
{
return super.clone();
}
catch (CloneNotSupportedException e)
{
throw new InternalError(e.toString());
}
}

This way, you don't have to put calls to clone() in a try block,
because InternalError is an unchecked exception. But if a
CloneNotSupportedException were to be thrown, you're still propagating
an exception.

For more information, see:
http://java.sun.com/developer/JDCTechTips/2001/tt0306.html
Can someone tell me is the 'duplicate()' is safe, why should I use clone()
and not my own cloning code (same as C++ copy constructors)?

The reason not to write your own cloning code (that creates a new
object of the same class and then sets all of the member values
manually) is that if someone tries to clone a subclass of your class
the returned object will be an instance of your class, and not the
subclass.
Does Object.clone() clones my private variables too in MyClass?

Yes. And when called on a subclass of your class, the subclass' member
variables will be cloned as well.
 

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,769
Messages
2,569,581
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top