Win a copy of Fixing your Scrum this week in the Agile forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Rob Spoor
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Junilu Lacar
  • Tim Cooke
Saloon Keepers:
  • Tim Holloway
  • Piet Souris
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
Bartenders:
  • Frits Walraven
  • Himai Minh

Effective Java: Typesafe enum pattern

 
Sheriff
Posts: 16570
272
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Joshua,
Welcome to JavaRanch!
You mention in your article and book that the reason that the typesafe enum pattern is not used more heavily in the Java APIs is that it was unknown when most of the API was written. Is this pattern used more in new additions to the platform API?
Thanks!
 
Author and "Sun God"
Posts: 185
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Junilu,
Hi! I'm happy to say that as of release 1.4, the answer is "yes," the typesafe enum pattern is finally getting used in Java platform APIs, including (I believe) I18N, nio and others. In fact, I believe there were already a few uses in 1.3. If I get time later today, I'll look around for specific examples.
By the way, the HTML version of the chapter that you linked to is outdated. People interested in reading about typesafe enums should instead go to the PDF version, which is taken directly from the book, and contains many improvements: http://developer.java.sun.com/developer/Books/effectivejava/Chapter5.pdf . This is one of two chapters that are available on the JDC web site: http://developer.java.sun.com/developer/Books/effectivejava/index.html .
Regards,

------------------
Joshua Bloch
Author of Effective Java
 
Ranch Hand
Posts: 213
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Josh,
This pattern seems familiar. If I'm not mistaken, I think java.lang.Boolean uses something similar (it may not be the exact same pattern though).
As an aside, just wanna say that I'm about half-way through your book, and I simply cannot stop reading it I absolutely love it!
By the way I was one of the few lucky ones who barely managed to get a place in your packed JavaOne session this year
 
Joshua Bloch
Author and "Sun God"
Posts: 185
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Junaid Bhatra:
Hi Josh,
This pattern seems familiar. If I'm not mistaken, I think java.lang.Boolean uses something similar (it may not be the exact same pattern though).


Boolean is very close to being a typesafe enum, but not quite there, because it has a public constructor. (In fact, it didn't even have a static factory that took a boolean until 1.4.) This means that programmers can create as many copies of each constant as they want, and you can't compare the constants using == . It's unfortunate that Boolean has a public constructor, but too late to change it.
That said, there are a few classes in early releases that used something very close to the typesafe enum pattern. Many people developed it independently around '96-'97 (and perhaps earlier), but it didn't become widely known until recently.
I'm thrilled that you're enjoying my book, and that you got into (and presumably enjoyed) my talk.
Thanks,

------------------
Joshua Bloch
Author of Effective Java
 
Junilu Lacar
Sheriff
Posts: 16570
272
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I got a chance to browse a couple of books last week and found some twists to the Typesafe Enum pattern:
The first twist was from "Java 2 Performance and Idiom Guide" by Craig Larman and Rhett Guthrie. They declared the typesafe enum constants in an interface. The motivation was allow a class to have direct access to the constants without having to specify the interface name by simply implementing the interface. The only problem I saw with the approach was if a class implemented two typesafe enum interfaces that happened to have the same constant names, you would still need to qualify the constants with their respective interface names. It's an interesting approach but IMO, the typing you save by not having to qualify the constant is not worth the risk of bugs creeping in because you didn't.
"Java in Practice" by Nigel Warren and Philip Bishop discuss the second twist which addresses the issue of defining a constant enum that represents null. The solution in the book involves using a proxy class and a valueOf() class method.
Has anybody else here read the above and if so, what are your thoughts? Josh... ?

[This message has been edited by JUNILU LACAR (edited July 23, 2001).]
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Grrr... I'm still waiting for my copy of Josh's book, as bookpool went temporarily out of stock immediately after I placed my order. Worth noting - bookpool is generally the cheapest place to get technical books, but not the fastest. Obviously, there's a connection here.
In the meantime though, I do have Craig Larman's book. I don't think the issue you raise is really a problem. In the event that you implement two interfaces which contain different fields with the same name, and you refer to the name without qualifying it with the interface name, the compiler will promptly notify you of the problem. Much like if you import java.util.* and javax.swing.* in the same file and refer to List - you are forced to qualify the reference as java.util.List or javax.swing.List. There's no chance of a subtle error here - if it's an issue, it will be made obvious.
Craig Larman notes the problem that the interface with the constants needs access to the private constructor of the enum class. He solved this with a small package, replacing the private constructor with a package-access constructor. An alternate solution I came up with is to use a static member interface:
<code><pre>public final class ColorCode {

private ColorCode() {}

interface Values {
ColorCode RED = new ColorCode();
ColorCode GREEN = new ColorCode();
ColorCode BLUE = new ColorCode();
}
}
</pre></code>
Now outside classes can declare that they implement ColorCode.Values, and then they can refer to RED, GREEN, and BLUE without need for further qualification. ColorCode is still uninstantiable except through these constant fields, and no extra package is needed.
I don't have "Java in Practice", so I can't comment on that without more info.
[This message has been edited by Jim Yingst (edited July 25, 2001).]
 
Junilu Lacar
Sheriff
Posts: 16570
272
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Jim,
Your static member interface solution is elegant. Really nice. You're right about the name conflict issue, too. I don't know why I worry so much about those things I'll try to recall more about the variation in "Java in Practice" and post some code later.

 
Joshua Bloch
Author and "Sun God"
Posts: 185
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu,
Hi. Sorry about the delay in replying; I've been very busy fixing bugs in 1.4

Originally posted by JUNILU LACAR:
I got a chance to browse a couple of books last week and found some twists to the Typesafe Enum pattern:
The first twist was from "Java 2 Performance and Idiom Guide" by Craig Larman and Rhett Guthrie. They declared the typesafe enum constants in an interface. The motivation was allow a class to have direct access to the constants without having to specify the interface name by simply implementing the interface. The only problem I saw with the approach was if a class implemented two typesafe enum interfaces that happened to have the same constant names, you would still need to qualify the constants with their respective interface names. It's an interesting approach but IMO, the typing you save by not having to qualify the constant is not worth the risk of bugs creeping in because you didn't.


I do not recommend this "anti-pattern," which I call the constant interface. In fact, I have an item largely devoted to its shortcomings (Item 17: "Use interfaces only to define types"). Quoting from this item:
The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class�s exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the con-stants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.

"Java in Practice" by Nigel Warren and Philip Bishop discuss the second twist which addresses the issue of defining a constant enum that represents null. The solution in the book involves using a proxy class and a valueOf() class method.


I glanced at the Nigel and Warren book, and I can't say that I recommend this technique. The problem is that there are bugs that might result in null being passed to a method that expects a typesafe enum. Using null as a legitimate constant value masks these bugs, violating the "fail fast" principle. A bug that would otherwise be quickly discovered and corrected could instead remain undiscovered indefinitely, silently causing harm. In essence, this technique throws away one of the advantages of the typesafe enum pattern: that it is impossible to make a legitimate constant out of whole cloth.
Regards,


------------------
Joshua Bloch
Author of Effective Java
 
Those who dance are thought mad by those who hear not the music. This tiny ad plays the bagpipes:
the value of filler advertising in 2021
https://coderanch.com/t/730886/filler-advertising
reply
    Bookmark Topic Watch Topic
  • New Topic