首先咱们依旧是使用饿汉式做为测试。咱们把以前写的饿汉式的代码贴上来。java
public class HungrySingleton {
private final static HungrySingleton hungrySingleton;
static{
hungrySingleton = new HungrySingleton();
}
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
复制代码
而后咱们在测试类中使用反射来对这个单例进行攻击。测试
public class SingletonTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException {
HungrySingleton instance = HungrySingleton.getInstance();
Class<HungrySingleton> hungrySingletonClass = HungrySingleton.class;
Constructor<HungrySingleton> constructor = hungrySingletonClass.getConstructor();
constructor.setAccessible(true);
HungrySingleton newInstance = constructor.newInstance();
System.out.println(instance == newInstance);
}
复制代码
这个输出结果可想而知false。那么咱们怎么样防治这种反射攻击呢?下面咱们给出一种解决方案spa
private final static HungrySingleton hungrySingleton;
static{
hungrySingleton = new HungrySingleton();
}
private HungrySingleton(){
if(hungrySingleton != null){
throw new RuntimeException("单例构造器禁止反射调用");
}
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
复制代码
咱们再使用这个测试类进行测试就发现报出异常。那这是饿汉式的单例若是是懒汉式的单例呢?可否经过这种方式来实现?答案是不能。至于缘由的你们想一想就知道了。懒汉式一开始加载的时候成员变量是null,也就没法经过判断是否为null来阻止反射获取实例。code