简介
说明
本文介绍Java破坏单例模式的方法。
单例模式(Singleton Pattern)是指确保一个类只有一个实例,并提供一个全局访问点。破坏单例模式的话,就是说可以创建出两个或两个以上的实例。本文通过静态内部类方式进行说明。
破坏单例的方法
破坏单列模式的方式
- 反射
- 序列和反序列化
- 使用不同的类加载器
上边1, 2都可以用枚举来解决,具体见:此文。
反射
破坏单例模式
单例类
package org.example.a;
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
测试类
package org.example.a;
import java.lang.reflect.Constructor;
public class Demo {
public static void main(String[] args) {
Class<?> singletonClass = Singleton.class;
try {
Constructor c = singletonClass.getDeclaredConstructor(null);
c.setAccessible(true);
Object singleton1 = c.newInstance();
Object singleton2 = c.newInstance();
System.out.println(singleton1 == singleton2);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
执行结果(创建出了两个不同的实例)
false
防止反射破坏单例模式
在构造函数里防止反射。
单例类
package org.example.a;
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {
if (SingletonHolder.INSTANCE != null) {
throw new RuntimeException("不允许通过反射创建实例");
}
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
测试类(通过反射获得实例)
package org.example.a;
import java.lang.reflect.Constructor;
public class Demo {
public static void main(String[] args) {
Class<?> singletonClass = Singleton.class;
try {
Constructor c = singletonClass.getDeclaredConstructor(null);
c.setAccessible(true);
Object singleton1 = c.newInstance();
System.out.println("singleton1 instance create successfully");
Object singleton2 = c.newInstance();
System.out.println("singleton2 instance create successfully");
System.out.println(singleton1 == singleton2);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
执行结果
Caused by: java.lang.RuntimeException: 不允许通过反射创建实例
测试类(通过静态方法获得实例)
package org.example.a;
public class Demo {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println("singleton create successfully");
}
}
执行结果
singleton create successfully
防止反射破坏单例模式的原理
1.用getInstance
调用到new Singleton()时,此时INSTANCE是null,所以不会报错。
2.用反射
调用构造方法时,调用到Singleton.INSTANCE,然后会再new Singleton()赋值给Singleton.INSTANCE,此时,Singleton.INSTANCE不为null。
序列化与反序列化
此内容仅限VIP查看,请先登录

请先 !