Java 创建单例对象,最好的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19436285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 17:08:27  来源:igfitidea点击:

Creating singleton object, best way

javasingleton

提问by Harke

I want to create a singleton object and I found 3 ways, which one is better and why are others bad. The constructor is assumed to be private.

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

Method 1:

方法一:

class ClassX{  
   private static ClassX objX = null;

      static{
          objX = new ClassX();
      }

   //get objX method
 }

Method 2:

方法二:

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

   //get objX method
 }

Method 3:

方法三:

 class ClassX{  
   private static ClassX objX = null;

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

采纳答案by Rahul Tripathi

You can try to use an enum like this:-

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

public enum Foo
{
   INSTANCE;
}

Also check out the related answer:- What is an efficient way to implement a singleton pattern in Java?

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

Quoting few lines from the Enforce the Singleton Property with a Private Constructor or an enum Typewhich Stephen Denne has used in the above answer:-

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

This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.

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

回答by lummycoder

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;
    }
}

回答by bstempi

Method 3 is not thread-safe, meaning that if multiple callers come in at the same time, you can end up with more than one singleton. Method 1 and 2 will work and are essentially the same thing. You might want to consider this example, using double check locking:

方法 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;
   }
}

It may seem silly, but double-checked locking is thread safe and far cheaper than using a synchronizedversion of getInstance(), which makes absolutely sure that you will only ever have 1 ClassXinstance. Also, this allows you to pass data into getInstance()should you choose to use it as a factory or service locator who's job it is to create or store singletons.

这可能看起来很愚蠢,但双重检查锁定是线程安全的,并且比使用 的synchronized版本便宜得多getInstance(),这绝对确保您只有 1 个ClassX实例。此外,getInstance()如果您选择将数据用作创建或存储单例的工厂或服务定位器,这允许您将数据传递到其中。

回答by csn

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

创建一个静态最终私有实例并使用静态 getter 访问它,并且构造函数当然是私有的。

private static final ClassX classX = new ClassX();

public static ClassX getInstance(){
  return classX;
}

or use dependency injection.

或使用依赖注入。

回答by millimoose

You do not need lazy initialisation:

您不需要延迟初始化:

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

This probably won't resist serialization or reflection, but it should be good enough w/r/t thread safety. (Of course, you could also just create only one instance as I've implied in my comments.)

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