零实例枚举vs私有构造函数用于防止实例化

一些实用程序类(想想java.lang.Math )只声明一个私有构造函数,以防止实例化该类。

有没有什么特别的原因可以解释为什么这些类没有实现0-instance enum? 在我看来,enums是一种比构造函数上的访问修饰符更直接的控制实例化的方法。 它还可以防止类本身创建实例,这些实例既可以防止程序员在脚中射击,也可以向外传递任何实例的保证。

约书亚布洛赫主张使用枚举作为单身人士。 0-instance实用程序类不应该具有相同的优点吗?

我的问题: 0实例枚举与私有构造函数的优缺点是什么? (我个人认为使用枚举没有任何缺点,尽管私有构造函数似乎是更普遍的方法。)

(我知道java.lang.Math早于enum 。我在这里说1.5+代码。)

那么,总结一下到目前为止的答案和评论:

支持0实例枚举的参数:

  • Enum解决了控制类实例化的问题,这正是0实例实用程序类所需要的。

  • Weekday有7个实例, Month有12个, MySingleton有1个(并且应该根据Joshua Bloch通过枚举实现), MyUtilityClass有0个实例。 最后一个案例和前一个案例之间没有概念上的区别。

针对0实例枚举的参数:

  • 不遵循最不惊讶的原则; 当人们看到枚举时,他们希望它遵循非空的枚举的教科书示例,例如工作日,状态代码等。

  • 0实例枚举是一个没有被广泛使用的习语,因此不是其他程序员容易识别的东西。 也就是说它比使用私有构造函数更不易读。

  • 枚举使用隐式合成方法混乱,这意味着这些名称不允许使用自定义方法。 此外,公共API公开不应使用的方法的事实可能从笨拙到破碎。

其他说明

  • 相关问答 。

  • Peter Lawrey关于这个主题的博客文章 。

枚举无法实例化的事实是副作用。 当你宣称某个东西为枚举时,人们会认为它是一个枚举; 它将在IDE,代码分析工具中显示为枚举,无论如何。

遵循最不惊讶的原则,并且考虑到用户不关心你如何在内部实现这一点,我认为最好使用私有构造函数,并且从该构造函数中抛出一个Error ,前提是有人试图用reflection实例化它。

我不知道这两种方法都有任何技术缺陷。

至于优雅,这是一个意见问题,而且(IMO)与大多数计算机程序的真实目的并不特别相关。

相比之下,可读性,可维护性和正确性是与目的相关的属性。 有助于使程序可读的一个方面是使用其他程序员可以容易识别的习语。 零实例enum类型是一个有趣的想法……但私有构造函数是防止实例化的既定惯用语。