Some utility classes (think java.lang.Math
) declares only a private constructor in order to prevent instantiation of the class.
Is there any particular reason for why such classes are not implemented in terms of a 0-instance enum? It seems to me like enums is a more direct way of controlling instantiation than access modifiers on constructors. It also prevents the class itself from creating instances which both prevent the programmer from shooting himself in the foot and convey a guarantee outwards of no instances.
Joshua Bloch advocates the use of enums for singletons. Shouldn't the same benefits apply to 0-instance utility classes?
My question: What are the pros/cons of 0-instance enums vs private constructors. (I personally see no drawbacks of using an enum, though private constructors seems to be the more prevalent approach.)
(I know java.lang.Math
predates enum
. I'm talking 1.5+ code here.)
The enum constructor must be private . You cannot use public or protected constructors for a Java enum . If you do not specify an access modifier the enum constructor it will be implicitly private .
We need the enum constructor to be private because enums define a finite set of values (SMALL, MEDIUM, LARGE). If the constructor was public, people could potentially create more value. (for example, invalid/undeclared values such as ANYSIZE, YOURSIZE, etc.). Enum in Java contains fixed constant values.
An enum can, just like a class , have attributes and methods. The only difference is that enum constants are public , static and final (unchangeable - cannot be overridden). An enum cannot be used to create objects, and it cannot extend other classes (but it can implement interfaces).
Enum cannot have a default no-argument constructor and all its constructors (if any) are private; therefore, it is redundant to specify them explicitly. Note that the enum constructor classes are implicit and do not require new keyword.
The fact that enums cannot be instantiated is a side-effect. When you declare something as an enum, people would expect it to be an enum; it will appear as enum in the IDE, code analysis tools, whatever.
Following the principle of least astonishment, and given that the user doesn't care of how you internally achieve that, I think it's better to use a private constructor, and also throw an Error
from that constructor, provided someone tries to instantiate it with reflection.
So, to summarize the answers and comments so far:
Arguments supporting 0-instance enums:
Enum solves the problem of controlling instantiation of classes which is precisely what a 0-instance utility class needs.
Weekday
has 7 instances, Month
have 12, MySingleton
has 1 (and should according to Joshua Bloch be implemented by means of an enum) and MyUtilityClass
has 0 instances. There is no conceptual difference between the last case and the former ones.
A 0-instance enum guarantees that no instance will be created, not even from within the class itself.
Arguments against 0-instance enums:
Does not follow the principle of least astonishment; when people see an enum, they expect it to follow the text-book examples of non-empty enums such as weekdays, status codes etc.
The 0-instance enum is an idiom not widely used and thus not something other programmers recognize easily. I.e. it's less readable than using private constructors.
Enums are cluttered with implicit synthetic methods, which means that those names are not allowed for custom-defined methods. Furthermore, the fact that a public API exposes methods which should not be used can range from awkward to broken.
Other notes
Related question and answer.
Blog post on the subject by Peter Lawrey.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With