Java 如何确保JVM中只有一个类实例?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27782769/
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
How to make sure that there is just one instance of class in JVM?
提问by Joe
I am developing a design pattern, and I want to make sure that here is just one instance of a class in Java Virtual Machine, to funnel all requests for some resource through a single point, but I don't know if it is possible.
我正在开发一种设计模式,我想确保这里只是 Java 虚拟机中一个类的一个实例,通过一个点汇集对某些资源的所有请求,但我不知道这是否可能。
I can only think of a way to count instances of a class and destroy all instance after first is created.
我只能想到一种方法来计算类的实例并在创建第一个实例后销毁所有实例。
Is this a right approach? If not, is there any other way?
这是一个正确的方法吗?如果没有,还有其他方法吗?
采纳答案by Sufiyan Ghori
Use the singletonpattern. The easiest implementation consists of a private constructor
and a field
to hold its result, and a static
accessor method with a name like getInstance()
.
使用单例模式。最简单的实现包括 aprivate constructor
和 afield
来保存它的结果,以及static
一个名字像getInstance()
.
The private field can be assigned from within a static initializer block or, more simply, using an initializer. The getInstance()
method (which must be public) then simply returns this instance,
私有字段可以从静态初始化程序块中分配,或者更简单地,使用初始化程序。该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";
}
}
Note that the method of using “lazy evaluation” in the getInstance()
method (which
is advocated in Design Patterns), is not necessary in Java because Java already uses “lazy
loading.” Your singleton class will probably not get loaded unless its getInstance()
is called, so there is no point in trying to defer the singleton construction until it's needed
by having getInstance()
test the singleton variable for null
and creating the singleton
there.
请注意,方法中使用“延迟评估”的getInstance()
方法(在设计模式中提倡),在 Java 中不是必需的,因为 Java 已经使用了“延迟加载”。您的单例类可能不会被加载,除非它getInstance()
被调用,所以通过getInstance()
测试单例变量null
并在那里创建单例来尝试推迟单例构造是没有意义的。
Using this class is equally simple: simply get and retain the reference, and invoke methods on it:
使用这个类同样简单:只需获取并保留引用,然后调用它的方法:
public class SingletonDemo {
public static void main(String[] args) {
Singleton tmp = Singleton.getInstance();
tmp.demoMethod();
}
}
Some commentators believe that a singleton should also provide a public final
clone()
method that just throws an exception, to avoid subclasses that “cheat” and
clone()
the singleton. However, it is clear that a class with only a private constructor
cannot be subclassed, so this paranoia does not appear to be necessary.
一些评论家认为,单例还应该提供一个公共 final
clone()
方法,它只是抛出异常,以避免“作弊”和clone()
单例的子类
。但是,很明显只有一个私有构造函数的类不能被子类化,所以这种偏执似乎没有必要。
回答by Todd
You want the Singleton
pattern. There is an excellent discussionof how to implement this properly. If you do this right, there will only ever be one instance of the class.
你想要Singleton
图案。关于如何正确实现这一点有一个很好的讨论。如果你做对了,这个类将永远只有一个实例。
Essentially what you are going to do is create a class, hold a single instantiated object of that class at the static level, and provide a static accessor to get it (getInstance()
or similar). Make the constructor final so people can't create their own instances out of the blue. That link above has plenty of great advice on how to do this.
基本上你要做的是创建一个类,在静态级别保存该类的单个实例化对象,并提供一个静态访问器来获取它(getInstance()
或类似的)。将构造函数设为 final,这样人们就不能突然创建自己的实例。上面的链接有很多关于如何做到这一点的好建议。
回答by Willem Van Onsem
That's the well known Singleton pattern: you can implement this as follows:
这就是众所周知的单例模式:您可以按如下方式实现:
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;
}
}
You then call for the instance (like you would constructing a non-singleton) with:
然后你调用实例(就像你构造一个非单例一样):
SingletonClass.getInstance();
But in literature, a Singletonis in general considered to be a bad design idea. Of course this always somewhat depends on the situation, but most programmers advice against it. Only saying it, don't shoot on the messenger...
但在文献中,单例通常被认为是一个糟糕的设计理念。当然,这总是在某种程度上取决于情况,但大多数程序员建议不要这样做。只说,不要对着信使开枪……
回答by Chandan Rajput
For that you need to use singleton pattern, I am just posting a demo code for that that may useful for your understanding.
为此,您需要使用单例模式,我只是发布了一个演示代码,可能对您的理解有用。
E.g: If I want only one object for this Connect
class:
例如:如果我只想要这个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;
}
}
Here the constructor is private, so no one can use new
keyword to make a new instance.
这里的构造函数是私有的,所以没有人可以使用new
关键字来创建一个新的实例。
回答by Stephen C
I can only think of a way to count instances of a class and destroy all instance after first is created. Is this a right approach ? If not, is there any other way ?
我只能想到一种方法来计算类的实例并在创建第一个实例后销毁所有实例。这是正确的方法吗?如果没有,还有其他方法吗?
The correct technical approach is to declare all of the constructors for the class as private
so that instances of the class can only be created by the class itself. Then you code the class only ever create one instance.
正确的技术方法是声明类的所有构造函数,以便类的private
实例只能由类本身创建。然后你对类进行编码,只创建一个实例。
Other Answers show some of the ways to implement this, according to the "Singleton" design pattern. However, implementing a singleton like this has some drawbacks, including making it significantly harder to write unit tests.
根据“单例”设计模式,其他答案显示了实现这一点的一些方法。然而,实现这样的单例有一些缺点,包括使得编写单元测试变得非常困难。
回答by Jool
There is a school of thought that considers the Singleton pattern to in fact be an anti-pattern.
有一种思想流派认为单例模式实际上是一种反模式。
Considering a class A that you only wish to have one of, then an alternative is to have a builder or factory class that itself limits the creation of the number of objects of Class A, and that could be by a simple counter. The advantage is that Class A no longer needs to worry about that, it concentrates on its real purpose. Every class that uses it no longer has to worry about it being a singleton either (no more getInstance() calls).
考虑到您只希望拥有一个 A 类,那么另一种选择是拥有一个构建器或工厂类,它本身限制了 A 类对象数量的创建,这可以通过一个简单的计数器来实现。好处是A班不再需要担心,它专注于它的真正目的。每个使用它的类都不再需要担心它是单例(不再调用 getInstance())。
回答by Vlad Lifliand
Use enum. In Java enum is the only true way to create a singleton. Private constructors can be still called through reflection.
使用枚举。在 Java 中,枚举是创建单例的唯一真正方法。私有构造函数仍然可以通过反射调用。
See this StackOverflow question for more details: Implementing Singleton with an Enum (in Java)
有关更多详细信息,请参阅此 StackOverflow 问题: Implementing Singleton with an Enum (in Java)
Discussion: http://javarevisited.blogspot.com/2012/07/why-enum-singleton-are-better-in-java.html
讨论:http: //javarevisited.blogspot.com/2012/07/why-enum-singleton-are-better-in-java.html
回答by Alex Vipul Verma
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();
}
}
回答by Ravindra babu
I prefer lazy singleton class, which overrides readResolvemethod.
我更喜欢懒惰的单例类,它覆盖了readResolve方法。
For Serializable and Externalizable classes, the readResolve method allows a class to replace/resolve the object read from the stream before it is returned to the caller. By implementing the readResolve method, a class can directly control the types and instances of its own instances being deserialized.
对于 Serializable 和 Externalizable 类,readResolve 方法允许类在返回给调用者之前替换/解析从流中读取的对象。通过实现 readResolve 方法,一个类可以直接控制自己被反序列化的实例的类型和实例。
Lazy singleton using /Initialization-on-demand_holder_idiom:
使用/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;
}
}
Key notes:
要点:
final
keyword prohibits extension of this class by sub-classingprivate
constructor prohibits direct object creation withnew
operator in caller classesreadResolve
prohibits creation of multiple instances of class during object de-serialization
final
关键字禁止通过子类化扩展此类private
构造函数禁止new
在调用者类中使用运算符直接创建对象readResolve
禁止在对象反序列化期间创建多个类实例