Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

The canonical object idiom

Defining a baseline set of functionality for objects

  • Print
  • Feedback

Page 3 of 5

It turns out that, so long as you implement Cloneable, Object's implementation of clone() will never throw CloneNotSupportedException. Object's implementation of clone() checks to see if the object's class implements Cloneable; if it does, it clones the object by making a direct field-by-field copy of the original in the clone. Only if the object's class doesn't implement Cloneable will Object's implementation of clone() throw CloneNotSupportedException. So if you implement Cloneable, you may as well catch CloneNotSupportedException just to keep it out of your clone()'s throws clause.

The one risk to heeding this advice is that when you remove CloneNotSupportedException from your clone()'s throws clause, you tie the hands of anyone who ever wants to disallow cloning in a subclass of your class. The customary way to disallow cloning in a subclass of some class that allows and supports cloning is to override clone() and throw CloneNotSupportedException. Thus, you should consider whether you want to enable subclasses to disallow cloning when you implement clone().

My opinion is that if you are not sure, you should catch CloneNotSupportedException, which effectively sets the policy that all subclasses will be clonable. I believe situations in which someone will want to disallow cloning in a subclass will be rare. Therefore, the ease of use you gain by not forcing clients to deal with CloneNotSupportedException outweighs the slight risk that you will be frustrating someone who wants to disallow cloning in a subclass at some point in the future.

Don't support cloning in immutable objects
If the object is immutable, you don't need to (and shouldn't) make it clonable. The reason you clone an object is so that the two instances can evolve independently thereafter. For example, you may clone an object before passing it to a method that alters the object. Because immutable objects can't evolve (their state doesn't ever change), there is no need to clone them. Everyone can safely share the same immutable instance.

Make equals() do a semantic compare
An important aspect of the canonical object idiom is implementing equals() such that it does a semantic comparison. Canonical objects override equals(), because the default implementation of equals() in class Object just returns true if one object '==' the other object. In other words, comparing two objects with equals() yields the same result, by default, as comparing to objects with Java's == operator. Why are there two ways to check objects for equality? Because they are supposed to be different.

Java's == operator simply checks to see if two references refer to the same object exactly. Invoking equals() on an object is supposed to do a semantic compare: if the two objects "mean the same thing," equals() should return true.

What does it mean for an object to "mean the same thing" as another object? Well, that's what you, as designer of a class, get to decide. In general, however, two objects are semantically equal when they have the same class and their states are equal. In other words, semantic equality means that:

  • Print
  • Feedback

Resources
  • Bill Venners' next book is Flexible Java http://www.artima.com/flexiblejava/index.html
  • Bill Venners is currently riding his bike through various European countries. As he encounters Internet cafes, he'll be posting reports about his trip. Follow along at
    http://www.artima.com/bv/travel/bike98.html
  • The discussion forum devoted to the material presented in this article http://www.artima.com/flexiblejava/fjf/canonical/index.html
  • Links to all previous design techniques articles http://www.artima.com/designtechniques/index.html
  • Recommended books on Java design, including information by the Gamma, et al., Design Patterns book http://www.artima.com/designtechniques/booklist.html
  • A transcript of an e-mail debate between Bill Venners, Mark Johnson (JavaWorld's JavaBeans columnist) and Mark Balbe on whether or not all objects should be made into beans http://www.artima.com/flexiblejava/comments/beandebate.html
  • Source packet that contains the example code used in this article http://www.artima.com/flexiblejava/code.html
  • Object orientation FAQ http://www.cyberdyne-object-sys.com/oofaq/
  • 7237 Links on Object Orientation http://www.rhein-neckar.de/~cetus/software.html
  • The Object-Oriented Page http://www.well.com/user/ritchie/oo.html
  • Collection of information on OO approach http://arkhp1.kek.jp:80/managers/computing/activities/OO_CollectInfor/OO_CollectInfo.html
  • Design Patterns Home Page http://hillside.net/patterns/patterns.html
  • A Comparison of OOA and OOD Methods http://www.iconcomp.com/papers/comp/comp_1.html
  • Object-Oriented Analysis and Design MethodsA Comparative Review http://wwwis.cs.utwente.nl:8080/dmrg/OODOC/oodoc/oo.html
  • Patterns discussion FAQ http://gee.cs.oswego.edu/dl/pd-FAQ/pd-FAQ.html
  • Patterns in Java AWT http://mordor.cs.hut.fi/tik-76.278/group6/awtpat.html
  • Software Technology's Design Patterns Page http://www.sw-technologies.com/dpattern/
  • Previous Design Techniques articles http://www.javaworld.com/topicalindex/jw-ti-techniques.html