Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

clone method call non-private, non-final methods

5 views
Skip to first unread message

puzzlecracker

unread,
Jul 23, 2008, 8:45:19 AM7/23/08
to
I saw it in the Effective Java book, though understanding still eludes
me (I suspect it goes on par with the constructor's contract). I don't
see implications whereby clone calls some public method to copy parts
of the object, resulting in the disaster or the end of the world sort
of a thing. Can someone illustrate that?


Thanks

Eric Sosman

unread,
Jul 23, 2008, 9:29:28 AM7/23/08
to

Are you sure you've read the prohibition correctly? I can
think of no reason to avoid calling public methods in a clone()
implementation, although there are excellent reasons to avoid
calling overridable methods, the same reasons to avoid calling
them from constructors. Are you sure you haven't read "public"
where EJ actually says "non-final?"

--
Eric Sosman
eso...@ieee-dot-org.invalid

puzzlecracker

unread,
Jul 23, 2008, 11:32:02 AM7/23/08
to
> esos...@ieee-dot-org.invalid

Yes, he refers to public (In clone chapter, 2nd edition), because, as
you said, they can be overridable.

What is the issue with that?

Eric Sosman

unread,
Jul 23, 2008, 12:45:24 PM7/23/08
to
puzzlecracker wrote:
> On Jul 23, 9:29 am, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>> puzzlecracker wrote:
>>> I saw it in the Effective Java book, though understanding still eludes
>>> me (I suspect it goes on par with the constructor's contract). I don't
>>> see implications whereby clone calls some public method to copy parts
>>> of the object, resulting in the disaster or the end of the world sort
>>> of a thing. Can someone illustrate that?
>> Are you sure you've read the prohibition correctly? I can
>> think of no reason to avoid calling public methods in a clone()
>> implementation, although there are excellent reasons to avoid
>> calling overridable methods, the same reasons to avoid calling
>> them from constructors. Are you sure you haven't read "public"
>> where EJ actually says "non-final?"
>
> Yes, he refers to public (In clone chapter, 2nd edition), because, as
> you said, they can be overridable.

I only have the first edition; perhaps the text has changed.
Note, though, that public does not imply overridable, nor does
non-overridable imply non-public. They are different beasts:

public void method1() {
// public and overridable
}

public final void method2() {
// public, but not overridable
}

void method3() {
// non-public, but overridable
}

final void method4() {
// non-public and not overridable
}

private void method5() {
// non-public and not overridable
}

As method1() through method4() illustrate, access and overridability
are mostly independent. method5() shows why it's only "mostly:" the
method can't be overridden because subclasses can't even see it, much
less override it. (A subclass can define its own method5(), but it's
not an override: it's an entirely independent method. If the superclass
calls method5(), it always gets its own method5() and not the one in
the subclass.)

> What is the issue with that?

If an overridable method is called from a constructor or as part
of clone() or of deserialization, the code that runs might belong to
an overriding subclass and not to the superclass being dealt with at
the moment. This lets the subclass' code "see" its own superclass-ness
in an incompletely initialized state, a source of surprises that are
seldom pleasant. I think EJ discusses this point somewhere, but my
copy is not within reach at the moment.

--
Eric....@sun.com

Daniel Pitts

unread,
Jul 25, 2008, 1:28:52 PM7/25/08
to

class MyClonable implements Clonable {
int cloneCount;

public void setCloneCount(int cloneCount) {
this.cloneCount = cloneCount;
}

protected MyClonable clone() {
MyClonable myClone = (MyClonable)super.clone();
myClone.setCloneCount(value + 1);
}
}

class MyClonableBreakers extends MyClonable {
public void setCloneCount(int cloneCount) {
this.cloneCount = 0;
}
}


The contract of clone() that is given by MyClonable is broken by the
derived class, without touching the clone method.

This is obviously a contrived example, but it shows what could happen
(maliciously or accidentally).

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

0 new messages