Today I was browsing through some questions on this site and I found a mention of an enum
being used in singleton pattern about purported thread safety benefits to such solution.
I have never used enum
s and I have been programing in Java for more than couple a years now. And apparently they changed a lot. Now they even do full blown support of OOP within themselves.
It is useful to know that
enums
are just like the other classes withConstant
fields and aprivate constructor
.For example,
The compiler compiles it as follows;
Why use any programming language feature? The reason we have languages at all is for
Enums improve both likelihood of correctness and readability without writing a lot of boilerplate. If you are willing to write boilerplate, then you can "simulate" enums:
Now you can write:
The boilerplate above has much the same effect as
Both provide the same level of checking help from the compiler. Boilerplate is just more typing. But saving a lot of typing makes the programmer more efficient (see 1), so it's a worthwhile feature.
It's worthwhile for at least one more reason, too:
Switch statements
One thing that the
static final
enum simulation above does not give you is niceswitch
cases. For enum types, the Java switch uses the type of its variable to infer the scope of enum cases, so for theenum Color
above you merely need to say:Note it's not
Color.RED
in the cases. If you don't use enum, the only way to use named quantities withswitch
is something like:But now a variable to hold a color must have type
int
. The nice compiler checking of the enum and thestatic final
simulation is gone. Not happy.A compromise is to use a scalar-valued member in the simulation:
Now:
But note, even more boilerplate!
Using an enum as a singleton
From the boilerplate above you can see why an enum provides a way to implement a singleton. Instead of writing:
and then accessing it with
we can just say
which gives us the same thing. We can get away with this because Java enums are implemented as full classes with only a little syntactic sugar sprinkled over the top. This is again less boilerplate, but it's non-obvious unless the idiom is familiar to you. I also dislike the fact that you get the various enum functions even though they don't make much sense for the singleton:
ord
andvalues
, etc. (There's actually a trickier simulation whereColor extends Integer
that will work with switch, but it's so tricky that it even more clearly shows whyenum
is a better idea.)Thread safety
Thread safety is a potential problem only when singletons are created lazily with no locking.
If many threads call
getInstance
simultaneously whileINSTANCE
is still null, any number of instances can be created. This is bad. The only solution is to addsynchronized
access to protect the variableINSTANCE
.However, the
static final
code above does not have this problem. It creates the instance eagerly at class load time. Class loading is synchronized.The
enum
singleton is effectively lazy because it's not initialized until first use. Java initialization is also synchronized, so multiple threads can't initialize more than one instance ofINSTANCE
. You're getting a lazily initialized singleton with very little code. The only negative is the the rather obscure syntax. You need to know the idiom or thoroughly understand how class loading and initialization work to know what's happening.Something none of the other answers have covered that make enums particularly powerful are the ability to have template methods. Methods can be part of the base enum and overridden by each type. And, with the behavior attached to the enum, it often eliminates the need for if-else constructs or switch statements as this blog post demonstrates - where
enum.method()
does what originally would be executed inside the conditional. The same example also shows the use of static imports with enums as well producing much cleaner DSL like code.Some other interesting qualities include the fact that enums provide implementation for
equals()
,toString()
andhashCode()
and implementSerializable
andComparable
.For a complete rundown of all that enums have to offer I highly recommend Bruce Eckel's Thinking in Java 4th edition which devotes an entire chapter to the topic. Particularly illuminating are the examples involving a Rock, Paper, Scissors (i.e. RoShamBo) game as enums.
In my opinion, all the answers you got up to now are valid, but in my experience, I would express it in a few words:
Use enums if you want the compiler to check the validity of the value of an identifier.
Otherwise, you can use strings as you always did (probably you defined some "conventions" for your application) and you will be very flexible... but you will not get 100% security against typos on your strings and you will realize them only in runtime.
From Java documents -
A common example is to replace a class with a set of private static final int constants (within reasonable number of constants) with an enum type. Basically if you think you know all possible values of "something" at compile time you can represent that as an enum type. Enums provide readability and flexibility over a class with constants.
Few other advantages that I can think of enum types. They is always one instance of a particular enum class (hence the concept of using enums as singleton arrives). Another advantage is you can use enums as a type in switch-case statement. Also you can use toString() on the enum to print them as readable strings.
ENum stands for "Enumerated Type". It is a data type having a fixed set of constants which you define yourself.