单例模式
1. 饿汉式
1.1 普通单例模式
/**
* 普通饿汉式
*/
class Singleton1 implements Serializable{
private static final Singleton1 INSTANCE=new Singleton1();
/**
* 防止 反射破坏单例
*/
private Singleton1(){
if (INSTANCE!=null){
throw new RuntimeException("Instance already exists");
}
System.out.println("private Singleton1() exec");
}
public static Singleton1 getInstance(){
return INSTANCE;
}
/**
* 防止 反序列化破环单例
* @return
*/
@Serial
public Object readResolve(){
return INSTANCE;
}
/**
* 检测 是否为饿汉式
*/
public static void other(){
System.out.println("==============================");
};
}
1.2 枚举单例模式
/**
* 枚举饿汉式
*/
enum Singleton2{
INSTANCE
}
2. 懒汉式
2.1 双检锁单例模式
/**
* 双检锁懒汉式
*/
class Singleton3{
private static volatile Singleton3 INSTANCE;
private Singleton3(){
System.out.println("private Singleton3() exec");
}
public static Singleton3 getInstance(){
if (INSTANCE==null) {
synchronized (Singleton3.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton3();
}
}
}
return INSTANCE;
}
/**
* 检测 是否为懒汉式
*/
public static void other(){
System.out.println("==============================");
};
}
2.2 内部类单例模式
/**
* 内部类懒汉式
*/
class Singleton4{
private Singleton4() {
System.out.println("private Singleton4() exec");
}
public static Singleton4 getInstance(){
return Inner.INSTANCE;
}
static class Inner{
private static Singleton4 INSTANCE=new Singleton4();
/**
* 检测 是否为懒汉式
*/
public static void other(){
System.out.println("==============================");
};
}
}
3. 破坏单例模式的方法
3.1 反射 (不能破坏枚举)
以普通单例模式为例
public class Main {
public static void main(String[] args) throws Exception {
Singleton1 instance = Singleton1.getInstance();
System.out.println(instance);
// 破坏单例
// 1. 反射
Constructor<Singleton1> constructor = Singleton1.class.getDeclaredConstructor();
constructor.setAccessible(true);
System.out.println(constructor.newInstance());
}
}
3.2 反序列化 (添加readResolve() 方法解决)
以普通单例模式为例
public class Main {
public static void main(String[] args) throws Exception{
Singleton1 instance = Singleton1.getInstance();
System.out.println(instance);
// 2. 反序列化
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);
outputStream.writeObject(instance);
ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
System.out.println(inputStream.readObject());
3.3 Unsafe (破坏一切)
以普通单例模式为例
public class Main {
public static void main(String[] args) throws Exception {
Singleton1 instance = Singleton1.getInstance();
System.out.println(instance);
// 3. Unsafe
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);
System.out.println(unsafe.allocateInstance(Singleton1.class));
}
}