四种单例模式-(破坏单例模式的三种方法)

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));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值