我有一个像这样的单身人士.
public class BookingFactory {
private final static BookingFactory instance;
static {
instance = new BookingFactory();
}
public static BookingFactory getInstance() {
return instance;
}
private BookingFactory() {
System.out.println("Object is created.");
}
}
public class Test {
BookingFactory instance = BookingFactory.getInstance();
instance = BookingFactory.getInstance();
Class<?> clazz = Class.forName("com.test.BookingFactory");
Constructor pvtConstructor = clazz.getDeclaredConstructors()[0];
// Set its access control
pvtConstructor.setAccessible(true);
// Invoke Private Constructor
BookingFactory notSingleton = (BookingFactory) pvtConstructor.newInstance(null);
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我看到了多条打印输出消息.有没有办法阻止这个单例从这个反射中被多次实例化?
谢谢.
lah*_*her 16
尝试使用enum.enums是一个很好的单身人士.
public static enum BookingFactory {
INSTANCE;
public static BookingFactory getInstance() {
return INSTANCE;
}
}
Run Code Online (Sandbox Code Playgroud)
您无法通过反射创建枚举.
getInstance()方法是多余的,但是更容易运行测试,抛出以下异常:
java.lang.IllegalArgumentException: Cannot reflectively create enum objects
at java.lang.reflect.Constructor.newInstance(Constructor.java:530)
at MultiSingletonTest.main(MultiSingletonTest.java:40)
Run Code Online (Sandbox Code Playgroud)
哦,看,有人已经给出了枚举答案.无论如何要张贴更完整.
Boh*_*ian 14
在构造函数中进行断言:
private BookingFactory() {
if (instance != null)
throw new IllegalStateException("Only one instance may be created");
System.out.println("Object is created.");
}
Run Code Online (Sandbox Code Playgroud)
改编自使用延迟加载时制作Java Singleton反射证明:
package server;
import java.lang.reflect.ReflectPermission;
import java.security.*;
public class JavaSingleton {
private static JavaSingleton INSTANCE = null;
private JavaSingleton() {
ReflectPermission perm = new ReflectPermission("suppressAccessChecks", "");
AccessController.checkPermission(perm);
}
synchronized public static final JavaSingleton getInstance() {
if (INSTANCE == null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
INSTANCE= new JavaSingleton();
return null;
}
});
}
return INSTANCE;
}
Run Code Online (Sandbox Code Playgroud)
构造函数检查调用者是否可以访问它.正如链接所解释的那样,需要创建一个允许Singleton类本身调用构造函数的策略文件.
抛出异常的方法不会阻止客户端在调用getInstance()之前反射性地调用构造函数.即使它确保只创建一个实例,也不能保证这是由Singleton类的getInstance()方法完成的.
访问控制检查将阻止此不必要的实例化.