关于单例和按需初始化持有人惯用语,有几件事需要解释。开始了:
1)访问修饰符:
通常,如果它们是私有的,则不能访问另一个类中的字段和方法。如果访问类在同一包中,则它们至少必须是包私有的(没有修饰符)。因此,实现它的正确方法是:
public class Singleton { ... private static class LazyHolder { static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return LazyHolder.INSTANCE; }}但是,JLS
6.6.1解释了:
否则,如果将成员或构造函数声明为私有,则仅当访问发生在包含成员或构造函数的声明的顶级类(第7.6节)的主体内时,才允许访问。
这意味着,将字段声明
INSTANCE为private仍然允许从顶级类内部进行访问
Singleton。但是编译器必须采取一些技巧来绕过private修饰符:它插入用于获取和设置此类字段的包专用方法。
实际上,您放置在哪个修饰符上都没有关系。如果它是公共的,那么仍然不能从之外的其他类访问它
Singleton。但是…我认为包私有访问是最好的。将其公开是没有道理的。将其设置为私有强制编译器执行一些技巧。将其打包为私有可以反映您所拥有的:从另一个班级访问班级成员。
2)如何实现单例:
如果您要考虑序列化,则单例实现会有些困难。Joshu
Bloch在他的书《有效的Java》中写了一个很重要的部分,关于实现单例。最后,他得出结论,为此简单地使用一个枚举,因为Java枚举规范提供了有关单例所需的所有特征。当然,这不再使用该成语了。
3)考虑设计:
在大多数设计决策中,单例不再拥有其位置。实际上,如果必须在程序中放置一个单例,则可能表明存在设计问题。注意:Singleton为某些数据或服务提供
全局访问 机制。这不是面向对象的。



