Java中单例的其他方式

2022-09-03 03:31:16

只是我在想写单例类的其他方法。那么这个类是否被视为单例类呢?

      public class MyClass{
            static Myclass myclass;

            static { myclass = new MyClass();}

            private MyClass(){}

            public static MyClass getInstance()
            { 
                return myclass;
            }
       }

因为静态块只运行一次。


答案 1

不,它不是。您没有声明 ,也不是 .代码也没有真正编译。myClassprivate static finalgetInstance()static

这是辛格尔顿的成语:

public class MyClass {
    private static final MyClass myClass = new MyClass();

    private MyClass() {}

    public static MyClass getInstance() {
        return myClass; 
    }
}

它应该是 ,这样其他人就无法直接访问它。它应该是这样的,所以只有一个。它应该是为了使它不能被重新分配。您还需要在声明期间直接实例化它,这样您就不必担心(那么多)线程化。privatestaticfinal

如果加载成本很高,并且您因此更喜欢延迟加载单例,那么请考虑单例持有者成语,它根据需要而不是在类加载期间进行初始化:

public class MyClass {
    private MyClass() {}

    private static class LazyHolder {
        private static final MyClass myClass = new MyClass();
    }

    public static MyClass getInstance() {
        return LazyHolder.myClass;
    }
}

但是,无论您是否需要单例,都应该设置大问号。通常不需要它。只是一个静态变量,枚举,工厂类和/或依赖注入通常是更好的选择。


答案 2

还有一种方法可以做到这一点:

public enum Singleton{
  INSTANCE("xyz", 123);

  // Attributes
  private String str;
  private int i;

  // Constructor
  Singleton(String str, int i){
    this.str = str;
    this.i = i;
  }
}

根据Josh Bloch的 Effective Java,这是在Java中实现Singleton的最佳方式。与涉及私有静态实例字段的实现不同,可以通过滥用反射和/或序列化来乘法实例化,枚举保证为单例。

枚举单例的主要限制是它们总是在类加载时实例化,并且不能懒惰地实例化。因此,例如,如果要使用运行时参数实例化单例,则必须使用其他实现(最好使用双重检查锁定)。


推荐