|
|
|
Sponsored Link •
|
|
Advertisement
|
Alternative ways to implement the idiom
If you wish to disallow cloning of an object, you can simply choose not
to implement Cloneable, unless a superclass already
implements Cloneable. In that case, you'll need to
override clone() and throw
CloneNotSupportedException. If a superclass
implementation of clone() has removed
CloneNotSupportedException from its throws
clause, you should either change that superclass or allow cloning in
the subclass.
If you wish to disallow serialization, you can simply choose not to
implement Serializable.
Note that defining finalize() is not part of this idiom. A
finalizer is not appropriate in general cases, although under certain
circumstances you may want to write a finalizer. For advice on writing
finalizers, follow the link from the Resources
section to a previous Design Techniques article on
that subject.
Note also that defining toString() is missing from the
list above. I left it out because I believe Object has a
reasonable default implementation for this method.
Object's toString() method returns a string
composed of the name of the class, an "at" sign ("@"), and the unsigned
hexadecimal representation of the hash code of the object. If you do
override toString, you should return a string that
"textually represents" the object. The returned result should be
concise, informative, and easy to read.
One other thing missing from the canonical object idiom is a no-arg
constructor. Any class that has a no-arg constructor and implements
Serializable is a JavaBean. See the Resources section for a link to a discussion of
when it is appropriate to make a class into a bean.
Idiom issues
To help spark some discussion on the Flexible Java Forum, a discussion
forum devoted to Java design topics, I will throw out some of the
issues that may present themselves with this idiom (see the Resources section for a link to the forum):
toString from my canonical object recipe?
InternalError from
the catch clause that catches CloneNotSupportedException?
My general advice (given in my "Designing with
Exceptions" article) is that programs should throw only exceptions,
never errors. Usually the VM throws the errors. But in this case, I
have implemented Cloneable. Thus, if
Object's clone() implementation throws
CloneNotSupported, I think that may qualify as an internal
error to me. Since this "internal error" will likely never happen, what
I throw probably isunimportant. But I'd still feel better about
throwing an exception rather than an error. Perhaps what we need is a
java.lang.ThisWasntSupposedToEverHappenException.
CloneNotSupportedException at all, because, as I described
above, it does tie the hands of anyone wishing to disallow cloning in a
subclass.
Next month
In next month's Design Techniques I'll talk about
composition and inheritance.
A request for reader participation
I encourage your comments, criticisms, suggestions, flames -- all kinds
of feedback -- about the material presented in this column. If you
disagree with something, or have something to add, please let me know.
You can either participate in a discussion forum devoted to this material or e-mail me directly at bv@artima.com.
About the author
Bill Venners has been writing software professionally for 12 years.
Based in Silicon Valley, he provides software consulting and training
services under the name Artima
Software Company. Over the years he has developed software for the
consumer electronics, education, semiconductor, and life insurance
industries. He has programmed in many languages on many platforms:
assembly language on various microprocessors, C on Unix, C++ on
Windows, Java on the Web. He is author of the book: Inside the Java
Virtual Machine, published by McGraw-Hill.
Reach Bill at bv@artima.com.
This article was first published under the name The Canonical Object Idiom in JavaWorld, a division of Web Publishing, Inc., September 1998.
|
Sponsored Links
|