是否存在可以完全阻止创建多个对象的单例设计?
请记住这个问题,请记住,在Java中,我们可以使用序列化 - 反序列化和反射来重新创建“单例对象”。
答案 0 :(得分:3)
是的,我们可以设计一个真正的单例类(也是线程安全的)
但是每个单例类只是给定类加载器中的单例,
在运行时不在整个JVM中。
有关详细信息,请查看这些相关问题。
What is an efficient way to implement a singleton pattern in Java?
How does Singleton behave when two threads call the "getInstance()" at the same time?
How to correctly make a thread safe Singleton Factory in Java?
答案 1 :(得分:2)
是的,Java 5引入了枚举,这些枚举不能通过序列化等创建其他实例。
在Java 5+中创建单例的标准方法是使用一个常量枚举。
答案 2 :(得分:1)
可能是或否,取决于您要采取的步骤以及您的想法。
纯粹在JVM中,我会说不。由不同类加载器加载的资源被认为是不同的。因此,无论您采取何种检查,您的单个Foo.class
文件都可以由不同的类加载器加载,并且将创建静态对象的两个实例。他们提到的静态变量会有所不同,因此其中一个变量无法看到已经创建了另一个变量。
但是,如果您愿意使用外部资源(例如本地文件系统上的文件,假设您肯定可以写入目录),那么它可能是可能的。这假设外部系统具有比较和设置或其他同步语义,否则您有潜在的竞争条件,可能导致两个潜在的实例看到另一个未运行,然后启动。
后一种情况可能是相关的,这取决于您如此确定第二个实例不存在的原因。如果是因为它可能会破坏某些外部资源,请将约束放在该资源本身上。
答案 3 :(得分:0)
你可以使用枚举来制作单例模式,这是最好的在java中实现单例,但要记住每个类加载器只有一个单例
Serializable singleton
public enum Elvis {
INSTANCE;
private final String[] favoriteSongs =
{ "ABC", "DEF" };
public void printFavorites() {
System.out.println(Arrays.toString(favoriteSongs));
}
}
答案 4 :(得分:0)
单元素枚举类型是实现单例的最佳方式。
它将免费提供序列化机制,并提供一个 铁定的保证反对多重实例化,即使面对复杂 序列化或反射攻击。
答案 5 :(得分:0)
是的,你可以在java中创建一个真正的单例类。
例如:
public class Foo {
private Foo f = null;
//More Variables
private Foo(){ //Constructor
}
public static Foo getInstance() {
if (f == null) { //f is the instance of the class Foo.
f = new Foo();
}
return f;
}
public void display() {
System.out.println("Display");
}
//...More Methods
}
In order to call, you may use it as:
Foo.getInstance().display();
每次调用getInstance()时,它只会在应用程序的生命周期内生成一次Foo类的实例。