13

Peter Lawrey writes about Two Uses of Enums that most people forget on his blog.

First of all, I hadn't forgotten - I hadn't even realised :)

These approaches are nice and concise - are there any benefits other than conciseness compared with the more traditional ways of achieving the same thing, such as using final classes with private constructors for utility classes?

Also, are there any issues (apart from confusing programmers who aren't expecting it)?

Community
  • 1
  • 1
Rich
  • 15,602
  • 15
  • 79
  • 126
  • Related: http://stackoverflow.com/questions/70689/efficient-way-to-implement-singleton-pattern-in-java/71399#71399 – Bert F Feb 14 '11 at 21:51
  • 2
    To the downvoters I would be very interested to know why this question has been downvoted. It's not the first question about how to do things "The Wrong Way", and, at the same time, it turns out that Java's 'bible' (Effective Java) actually recommends this approach at least in the case of singletons. – Rich Feb 15 '11 at 11:22

5 Answers5

13

It would seem more intuitive to me to use enums for real enumerations.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • 1
    There's no reason you can't do that and use them in other situations where they're beneficial as well. – ColinD Feb 14 '11 at 14:08
  • @ColinD - I just don't think it's intuitive. When I see an enum, I'd expect a set of colours, statuses etc. – Brian Agnew Feb 14 '11 at 16:07
  • 1
    @Brian: It may not be entirely intuitive, but the enum singleton pattern at least is one that anyone who reads _Effective Java_ should know and recognize (and really, everyone should read that). As I mention in my answer, though, I don't like the first use from the linked post and I think it's often a good idea to make enum singletons an internal detail that a class doesn't expose to users. – ColinD Feb 14 '11 at 18:25
  • You write: "It may not be entirely intuitive", and that is true. There're simple intuitive best practices you can use that don't require an enum. Why should I misuse one then? – Falcon Feb 14 '11 at 20:20
  • @ColinD aaaah, so it's in the _updated_ Effective Java - I've not read that yet! – Rich Feb 14 '11 at 20:50
  • Why ride on a horse when you can ride on a big dog, too? Clearly, for dwarfs the dog might be a real alternative! – Falcon Feb 14 '11 at 20:53
11

I don't really agree with the first use of an enum from that post. If you want an uninstantiable utility class, just give it a private constructor. It's that simple, and the enum provides no added benefit in that situation that I see.

The use of enums for singletons in utility classes is great, but I would generally try to keep the fact that an enum is being used an internal implementation detail. See, for example, Guava's Predicates class which uses an enum to enforce a single instance of certain Predicates like alwaysTrue(). It does not expose the enum to users though.

As far as other benefits: yes, there are other benefits such as built-in serializability and absolutely enforcing a single instance of an enum constant per classloader, even when deserializing.

mvg
  • 1,574
  • 4
  • 37
  • 63
ColinD
  • 108,630
  • 30
  • 201
  • 202
  • I'm sure people will ask why I accepted this post rather than the others - it's actually because of a comment made by @ColinD to another answer to this question - explaining that the enum singleton pattern is proposed in Effective Java - that made me want to give @ColinD the points :) – Rich Feb 16 '11 at 12:21
2

My first instinct in both cases was that they were nasty hacks.

In the case of the singleton however, I think that you could reasonably argue that, in a language where enum constants are first class objects, there is conceptually no difference between a singleton and an enum with only one value. I'm still not sure I'd actually use the technique though, especially since the singleton pattern is pretty unpopular for other reasons.

Using an enum for a utility class is harder to defend. There is no conceptual reason for a set of utility methods to be expressed as an enum (arguably there's no reason for them to be expressed as a class, but that's a whole other debate). It seems the only justification for implementing utility methods this way is to save a little bit of typing by ignoring established conventions.

Dan Dyer
  • 53,737
  • 19
  • 129
  • 165
1

In addition to the obfuscation concern of using Enums for things that are not enumerations, using Enums for singletons has the same downfalls as other ways of hard-coding singleton scope, basically it impedes testing and makes inheritance or other extension difficult. It's a much better idea to let singleton scope be controlled by a factory like in Spring.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • 1
    Certainly this is true for services and such, but there are other types of singletons for which using an `enum` can be a good idea. – ColinD Feb 14 '11 at 14:15
-1

I do not like this approach. Enums should be kept simple enumerations really. They should contain conversional logic at most. Using the enum as a singleton or interface looks like an obfuscated code to me.

Falcon
  • 3,150
  • 2
  • 24
  • 35
  • 1
    @Falcon: I don't agree that enums need to be "simple" or that they should at most contain conversion logic. An enum is good, for example, for modeling a set of possible states for some object and it can make a lot of sense to have each state constant have its own implementation of a set of state-specific abstract methods. – ColinD Feb 14 '11 at 14:28
  • I'd rather use a state pattern for such cases. This is a clear misuse of enums which are simply meant to be an enumeration. There's no benefit, there's just a wtf-worthy obfuscation. – Falcon Feb 14 '11 at 14:54
  • 2
    @Falcon: It's a "clear misuse" _in your opinion_. Java made enums full classes instead of glorified string constants for a reason. Josh Bloch suggests the use of enum singletons in _Effective Java_, citing their numerous advantages over traditional ways of implementing a singleton. Whether you like it or not, enums in Java are a construct for creating a class with a fixed set of instances... not just for simple behaviorless enumerations. – ColinD Feb 14 '11 at 15:55
  • Just because someone writes that in some book, it doesn't mean that you should do it that way. Why is the use of an enum preferable over a classical singleton? It isn't. It's just code obfuscation. If you need that much logic in an enum, it ain't an enum in the first place. And an enum is not a string constant, that's something entirely different. – Falcon Feb 14 '11 at 20:17
  • Obviously I've got more of a clue than you and the author of that book. – Falcon Feb 14 '11 at 21:01
  • 2
    @Falcon: "someone" in "some book"... good one! You seem to just have some fixed idea of what an enum must be and to be unwilling to accept the fact that Java enums are significantly more powerful than what you believe they should be. Code associated with enum constants may be "obfuscation" to you, but it's well understood by most Java developers I know of. – ColinD Feb 14 '11 at 21:04
  • You write: "You seem to just have some fixed idea of what an enum must be and to be unwilling to accept the fact that Java enums are significantly more powerful than what you believe they should be." Yes, i believe enums should not be that powerful for the purpose of maintenance and clean code. – Falcon Feb 14 '11 at 21:12
  • 1
    @Falcon: If there's behavior that is associated with an enum constant, it's better for maintainability and clean code to associate that behavior with the constant directly rather than doing a `switch` on the enum or some such elsewhere in your code. In my opinion. Anyway, this has clearly gotten a bit too heated so... just gonna have to agree to disagree here. – ColinD Feb 14 '11 at 21:34
  • I concur, but that's not we're talking about here. It's about using the enum as an easy way to implement a singleton or the enum as an utility class replacement. I don't think it is a clever replacement for utility classes, because in modern times you design them as a pojo class and inject them, so you don't loose the oop traits and you can maintain a low cohesion which also benefits unit testing. You don't want classical singletons pretty much because of the same thing. You just want enums to do a compile-time check on constants. – Falcon Feb 14 '11 at 21:50