我想创建一个单例对象,我找到了3种方法,其中一种更好,为什么其他方式不好。假设构造函数是私有的。
方法1:
class ClassX{
private static ClassX objX = null;
static{
objX = new ClassX();
}
//get objX method
}
方法2:
class ClassX{
private static ClassX objX = new ClassX();
//get objX method
}
方法3:
class ClassX{
private static ClassX objX = null;
public ClassX getInstance(){
if(objX == null)
return new ClassX();
else
return objX;
}
}
答案 0 :(得分:7)
您可以尝试使用这样的枚举: -
public enum Foo
{
INSTANCE;
}
另请查看相关答案: - What is an efficient way to implement a singleton pattern in Java?
引用Stephen Denne在上述答案中使用的Enforce the Singleton Property with a Private Constructor or an enum Type中的几行: -
这种方法在功能上等同于公共领域方法, 除了它更简洁,提供序列化机制 免费,并提供反对多重的铁定保证 实例化,即使面对复杂的序列化或 反思攻击。虽然这种方法尚未被广泛采用, 单元素枚举类型是实现单例的最佳方式。
答案 1 :(得分: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;
}
}
答案 2 :(得分:0)
方法3不是线程安全的,这意味着如果多个呼叫者同时进入,则最终可能会有多个单例。方法1和2将起作用并且基本上是相同的。您可能需要使用double check locking:
来考虑此示例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()
便宜得多,这绝对可以确保您只有1 ClassX
实例。此外,如果您选择将数据用作创建或存储单例的工作或服务定位器,则允许您将数据传递到getInstance()
。
答案 3 :(得分:0)
创建一个静态的最终私有实例&使用静态getter访问它,construtor是私有的。
private static final ClassX classX = new ClassX();
public static ClassX getInstance(){
return classX;
}
或使用依赖注入。
答案 4 :(得分:0)
您不需要延迟初始化:
class Foo {
public static final Foo INSTANCE = new Foo();
private Foo();
}
这可能不会抵抗序列化或反射,但它应该足够好w / r / t线程安全。 (当然,你也可以只创建一个我在评论中隐含的实例。)