如何在Java中创建一个不可变的单例?

cha*_*nce 5 java singleton immutability

不可变对象仅由其构造函数初始化,而单例由静态方法实例化.如何在Java中创建一个不可变的单例?

Sea*_*oyd 8

而单例由静态方法实例化

虽然这是通常的做法,但这绝不是唯一的方法.

在Java 1.5中,新版本的Singleton是枚举单例模式:

public enum Elvis{

INSTANCE // this is a singleton, no static methods involved

}
Run Code Online (Sandbox Code Playgroud)

由于枚举可以有构造函数,方法和字段,因此可以为它们提供所需的所有不可变状态.

参考:


此外,Singleton这个词留下了一些解释空间.Singleton意味着每个定义的范围只有一个对象,但范围可以是很多东西:

  • Java虚拟机 类加载器(感谢@保罗Ebermann提醒我):在这种情况下使用枚举初始化贯通的静态内部类的图案.这当然是单身人士通常所说的.
    小心:如果通过多个类加载器加载,枚举和所有其他单例都会被破坏.
  • 企业应用程序(在这种情况下,您需要一个容器管理的单例,例如Spring单例bean).这可以是每个VM的多个对象,也可以是每个VM的一个对象(当然,每个VM一个对象)
  • 线程(使用一个ThreadLocal)
  • 请求/会话(再次,您需要一个容器来管理它,Spring,Seam和其他几个人可以为您做到这一点)
  • 我忘了什么吗?

以上所有内容都可以变为不可变的,每个都以自己的方式(尽管容器管理的组件通常不容易)


San*_*rma 5

Sean指出的解决方案是一种很好的方式来初始化单身人士,如果他们的创作并不昂贵.如果您想要"延迟加载"功能,请查看初始化按需持有者习惯用法.

 // from wikipedia entry
 public class Singleton {

   // Private constructor prevents instantiation from other classes
   private Singleton() {
   }

   /**
    * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
    * or the first access to SingletonHolder.INSTANCE, not before.
    */
   private static class SingletonHolder { 
     public static final Singleton INSTANCE = new Singleton();
   }

   public static Singleton getInstance() {
     return SingletonHolder.INSTANCE;
   }

 }
Run Code Online (Sandbox Code Playgroud)