-2

我想创建一个单例对象,我找到了 3 种方法,哪种方法更好,为什么其他方法不好。构造函数被假定为私有的。

方法一:

class ClassX{  
   private static ClassX objX = null;

      static{
          objX = new ClassX();
      }

   //get objX method
 }

方法二:

 class ClassX{  
   private static ClassX objX = new ClassX();

   //get objX method
 }

方法三:

 class ClassX{  
   private static ClassX objX = null;

   public ClassX getInstance(){
      if(objX == null)
          return new ClassX();
      else
          return objX;
   }
 }
4

5 回答 5

7

您可以尝试使用这样的枚举:-

public enum Foo
{
   INSTANCE;
}

另请查看相关答案:-在 Java 中实现单例模式的有效方法是什么?

引用斯蒂芬丹恩在上述答案中使用的使用私有构造函数或枚举类型强制单例属性的几行:-

这种方法在功能上等同于公共字段方法,只是它更简洁,免费提供序列化机制,并提供针对多次实例化的铁定保证,即使面对复杂的序列化或反射攻击。虽然这种方法尚未被广泛采用,但单元素枚举类型是实现单例的最佳方式

于 2013-10-17T20:11:35.117 回答
1
class ClassX {
    private static volatile ClassX instance = null;

    private ClassX() { }

    public ClassX getInstance() {
        if (instance == null) {
            synchronized (ClassX.class) {
                if (instance == null) {
                    instance = new ClassX();
                }
            }
        }
        return instance;
    }
}
于 2013-10-17T20:16:36.367 回答
0

方法 3 不是线程安全的,这意味着如果多个调用者同时进来,您最终可能会得到多个单例。方法 1 和 2 将起作用并且本质上是相同的。您可能想考虑这个例子,使用双重检查锁定

Class ClassX{  
   private static ClassX objX = null;

   public static ClassX getInstance(){
      if(objX == null)
          synchronized(this) {
              if(objX == null)
              objX = new ClassX();
          }

      return objX;
   }
}

synchronized这可能看起来很傻,但是双重检查锁定是线程安全的,getInstance()并且比使用ClassX. getInstance()此外,如果您选择将数据用作创建或存储单例的工厂或服务定位器,这允许您将数据传递到其中。

于 2013-10-17T20:19:14.883 回答
0

您不需要延迟初始化:

class Foo {
    public static final Foo INSTANCE = new Foo();
    private Foo();
}

这可能不会抵抗序列化或反射,但它应该足够好 w/r/t 线程安全。(当然,您也可以只创建一个实例,正如我在评论中暗示的那样。)

于 2013-10-17T20:30:01.720 回答
0

create a static final private instance & access it using a static getter and the construtor is private ofcourse.

private static final ClassX classX = new ClassX();

public static ClassX getInstance(){
  return classX;
}

or use dependency injection.

于 2013-10-17T20:25:10.483 回答