单例模式的 破坏、预防 and 建议

1. 前言

单例模式我们大家都知道,但是,单例模式也是可以被破坏的。下面介绍单例的破坏与预防。

单例的破坏我所了解的主要有两种情况:

  1. 主要是利用反射来调用你私有化的构造方法来创建对象
  2. 利用序列化来破坏

2. 反射破坏情况

反射破坏主要是调用你私有化的构造方法来创建对象。

2.1 原始代码

package pers.lzy.singleton.hungry;

import java.io.Serializable;

public class SingleTon implements Serializable {
    
    

    // 构造方法私有化
    private SingleTon() {
    
    }

    // 初始化对象
    private final static SingleTon INSTANCE = new SingleTon();

    // 设置获取对象方法
    public static SingleTon getInstance () {
    
    
        return INSTANCE;
    }

}

2.2 破坏代码

你不是构造方法私有化了嘛?不给我调用,那我就反射强制调用。如下图

在这里插入图片描述

2.3 解决办法

既然你强制调用了我的构造方法,那我就再构造方法里面做文章。

思路:你调用我构造方法,我发现我已经创建过了,我就给你抛出异常,不让你反射调用。代码如下:

在这里插入图片描述

3. 序列化破环情况

序列化破坏的思路,就是将对象序列化,之后呢,在反序列化成为对象。这样反序列化的对象可能就是另一个对象了。此举将破坏单例

3.2 破环代码

在这里插入图片描述

3.3 解决办法

再单例类中写一个readResolve方法

在这里插入图片描述

3.4 jdk源码分析

你会好奇为什么写这么一个方法,就可以解决这个问题呢?跟踪一下jdk源码可知。如下图

在这里插入图片描述

4. 个人建议

个人建议,使用单例模式尽量使用枚举来实现。

4.1 为何要使用枚举实现单例?

观看源码 + 反编译可知,jdk在底层已经帮我们进行判断,所以枚举实现的单例是不可能被反射与序列化破坏的。那么jdk帮我们做的事儿,他能不靠谱?所以有大牛推荐此方式来实现单例。

枚举实现的单例是饿汉式的。

5. 总结

随便看看吧,也没什么东西,加油。

猜你喜欢

转载自blog.csdn.net/weixin_42041788/article/details/106764837