6

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.)

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • 6
    I don't see elegance here. A single private no-arg constructor is good enough for me. – duffymo Aug 05 '14 at 11:18
  • 1
    That's interesting. I find controlling instantiation by means of access modifiers on constructors to be kind of indirect compared to listing (0) instances in an enum. – aioobe Aug 05 '14 at 11:25
  • 1
    Related: http://stackoverflow.com/q/9618583/897024, especially this answer: http://stackoverflow.com/a/9618724/897024 – kapex Aug 05 '14 at 11:33
  • I'm sorry, but shouldn't StackOverflow questions be about specific programming problems? How is this on-topic? Regardless of the last sentence, which kind-of asks for a specific answer, it is first and foremost a flamebaity kind of question. – William F. Jameson Aug 05 '14 at 11:39
  • 1
    I'm asking if there are any issues with using 0-instance enums in Java that I've over looked. I'll try to reformulate so that it reads a bit more objectively. ...(done) – aioobe Aug 05 '14 at 11:42

3 Answers3

4

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.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • +1 This. It's all about the intent. – helpermethod Aug 05 '14 at 11:31
  • 3
    Also: Enums are cluttered with implicit synthetic methods which is not elegant if you plan to never use them. – kapex Aug 05 '14 at 11:32
  • *"people would expect it to be an enum"* -- Of course it's an enum. You probably mean to say "people expect it to have instances"? The principle of least astonishment I buy, although that's more a matter of familiarity with the use of an enum rathen than a technical argument. – aioobe Aug 05 '14 at 11:32
  • @aioobe I agree, if there were some other common reasons to have enums without enum constants, then it wouldn't be surprising any more. – kapex Aug 05 '14 at 11:36
  • none of these are technical arguments - both will work equally well – Bozho Aug 05 '14 at 11:37
  • 1
    This is a piece of opinion. I am always astonished when I see someone took the time to write a constructor just to prevent people from using it. – mauhiz Apr 09 '15 at 03:07
4

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

aioobe
  • 413,195
  • 112
  • 811
  • 826
2

I don't know of any technical drawbacks with either approach.

As for elegance, that is a matter of opinion, and (IMO) not particularly relevant to the real purpose(s) of most computer programs.

By contrast, readability, maintainability and correctness are properties that are relevant to purpose. And one aspect that helps to make a program readable is the use of idioms that other programmers can readily recognize. Zero-instance enum types are an interesting idea ... but private constructors are the established idiom for preventing instantiation.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    However, private constructors only prevent *outside* instantiation and do not guarantee no instances. That's aioobe's point, and it's a good one. – Marko Topolnik Aug 05 '14 at 12:04
  • Maybe ... but it is the standard idiom. Besides, if you want to be pedantic, a zero instance enum doesn't prevent someone from adding an instance later on. – Stephen C Aug 05 '14 at 12:23
  • 3
    "Standard idiom" is a good argument in favor of private constructor, but since it predates the enum, if all it has going for it is that it has historically been the standard idiom, that would appear to me as a reason to review that standard. – Marko Topolnik Aug 05 '14 at 12:27
  • Ultimately, what happens *inside* the class is a matter of programmer self-discipline. This sounds rather like "change for the sake of it". The benefit is ... small at best. And very much a matter of opinion. – Stephen C Aug 05 '14 at 12:28
  • 2
    The "self-discipline" argument could be used to shoot down practically any language safety feature, such as the entire static type system. There is much value to a plain and simple *guarantee* of certain properties. I do agree with your "small-at-best benefit", and I'd take it as the leading reason why the status quo has remained in effect. – Marko Topolnik Aug 05 '14 at 12:30
  • 1
    The best way to do that is to use annotations. The programmer needs to express intent explicitly rather than just rely on "emergent" properties that may be non-intentional. And that includes zero instance enums. (They might be placeholders, or a simple mistakes ...) – Stephen C Aug 05 '14 at 12:33