如何确保JVM中只有一个类实例?

我正在开发一个设计模式,我想确保这里只是Java虚拟机中一个类的一个实例,通过一个点来汇集对某些资源的所有请求,但我不知道它是否可行。

我只能想到一种计算类实例的方法,并在创建第一个实例后销毁所有实例。

这是一种正确的方法吗? 如果没有,还有其他方法吗?

使用单例模式。 最简单的实现包括一个private constructor和一个保存其结果的field ,以及一个名为getInstance()static访问器方法。

私有字段可以从静态初始化程序块中分配,或者更简单地使用初始化程序分配。 getInstance()方法(必须是公共的)然后只返回此实例,

 public class Singleton { private static Singleton instance; /** * A private Constructor prevents any other class from * instantiating. */ private Singleton() { // nothing to do this time } /** * The Static initializer constructs the instance at class * loading time; this is to simulate a more involved * construction process (it it were really simple, you'd just * use an initializer) */ static { instance = new Singleton(); } /** Static 'instance' method */ public static Singleton getInstance() { return instance; } // other methods protected by singleton-ness would be here... /** A simple demo method */ public String demoMethod() { return "demo"; } } 

请注意,在Java中不需要在getInstance()方法(设计模式中提倡getInstance()中使用“延迟求值”的方法,因为Java已经使用“延迟加载”。除非getInstance()否则您的单例类可能不会被加载getInstance()被调用,所以没有必要尝试推迟单例构造,直到需要getInstance()测试单例变量为null并在那里创建单例。

使用这个类同样简单:只需获取并保留引用,并在其上调用方法:

 public class SingletonDemo { public static void main(String[] args) { Singleton tmp = Singleton.getInstance(); tmp.demoMethod(); } } 

一些评论员认为单例还应该提供一个公共最终clone()方法,它只抛出一个exception,以避免“欺骗”和clone()单例的子类。 但是,很明显只有私有构造函数的类不能被子类化,所以这种偏执似乎不是必需的。

你想要Singleton模式。 关于如何正确实现这一点有一个很好的讨论 。 如果你这样做,那么只有一个类的实例。

基本上你要做的是创建一个类,在静态级别保存该类的单个实例化对象,并提供一个静态访问器来获取它( getInstance()或类似)。 使构造函数最终,这样人们就无法创建自己的实例。 上面的链接有很多关于如何做到这一点的好建议。

这是众所周知的Singleton模式:您可以按如下方式实现:

 public class SingletonClass { //this field contains the single instance every initialized. private static final instance = new SingletonClass(); //constructor *must* be private, otherwise other classes can make an instance as well private SingletonClass () { //initialize } //this is the method to obtain the single instance public static SingletonClass getInstance () { return instance; } } 

然后,您调用实例(就像您将构建非单例):

 SingletonClass.getInstance(); 

但在文学中, 单身人士通常被认为是一个糟糕的设计理念 。 当然,这在某种程度上取决于具体情况,但大多数程序员都反对。 只说出来,不要向信使开枪……

有一种思想流派认为单身人士模式实际上是一种反模式。

考虑到你只希望拥有A类的A类,那么另一种选择是拥有一个构建器或工厂类,它本身限制了A类对象数量的创建,并且可以通过一个简单的计数器。 优点是A级不再需要担心,它专注于其真正的目的。 每个使用它的类不再需要担心它是单例(不再需要getInstance()调用)。

使用枚举。 在Java中,enum是创建单例的唯一真正方法。 私有构造函数仍然可以通过reflection来调用。

有关更多详细信息,请参阅此StackOverflow问题: 使用Enum实现Singleton(在Java中)

讨论: http : //javarevisited.blogspot.com/2012/07/why-enum-singleton-are-better-in-java.html

我只能想到一种计算类实例的方法,并在创建第一个实例后销毁所有实例。 这是一种正确的方法吗? 如果没有,还有其他方法吗?

正确的技术方法是将类的所有构造函数声明为private以便类的实例只能由类本身创建。 然后你只编写类来创建一个实例。

根据“Singleton”设计模式,其他答案显示了实现这一点的一些方法。 但是,实现像这样的单例有一些缺点,包括使编写unit testing变得更加困难。

我更喜欢lazy singleton类,它会覆盖readResolve方法。

对于Serializable和Externalizable类,readResolve方法允许类在返回到调用方之前替换/解析从流中读取的对象。 通过实现readResolve方法,类可以直接控制被反序列化的自己的实例的类型和实例。

使用/ Initialization-on-demand_holder_idiom的懒惰单例:

 public final class LazySingleton { private LazySingleton() {} public static LazySingleton getInstance() { return LazyHolder.INSTANCE; } private static class LazyHolder { private static final LazySingleton INSTANCE = new LazySingleton(); } private Object readResolve() { return LazyHolder.INSTANCE; } } 

主要说明:

  1. final关键字禁止通过子类扩展此类
  2. private构造函数禁止在调用者类中使用new运算符创建直接对象
  3. readResolve禁止在对象反序列化期间创建多个类实例

为此你需要使用单例模式,我只是发布了一个可能对你理解有用的演示代码。

例如:如果我只想为此Connect类使用一个对象:

 public final class Connect { private Connect() {} private volatile static Connect connect = null; public static Connect getinstance() { if(connect == null) { synchronized (Connect.class) { connect = new Connect(); } } return connect; } } 

这里构造函数是私有的,因此没有人可以使用new关键字来创建新实例。

 class A{ private A(){ } public static A creator(A obj){ A ob=new A(); return ob; } void test(){ System.out.println("The method is called"); } } class Demo{ public static void main(String[] args){ A ob=null; ob=A.creator(ob); ob.test(); } }