枚举实现单例那些事儿

《Effective Java》一书中提到,单元素的枚举类型,功能完整、使用简洁、无偿提供了序列化机制,在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点,被作者认为是实现单例模式的最佳方法(也是一种饿汉式)。

实现非常简单:

public enum Singleton {  
    INSTANCE;  
    public void getOtherMethod() {  
    }  
} 

调用也非常简单:

Singleton.INSTANCE.getOtherMethod();

那么,枚举是如何保证线程安全的呢?首先我们来看一个简单的枚举类。

public enum DemoEnum {
	FIRST,SECOND,THIRD,FOURTH
}

然后将它反编译,看看这段代码是如何实现的

public final class DemoEnum extends Enum {
    private DemoEnum(String s, int i) {
        super(s, i);
    }
    public static DemoEnum[] values() {
    	DemoEnum at[];
        int i;
        DemoEnum at1[];
        System.arraycopy(at = ENUM$VALUES, 0, at1 = new T[i = at.length], 0, i);
        return at1;
    }

    public static DemoEnum valueOf(String s) {
        return (DemoEnum)Enum.valueOf(demo/DemoEnum, s);
    }

    public static final DemoEnum FIRST;
    public static final DemoEnum SECOND;
    public static final DemoEnum THIRD;
    public static final DemoEnum FOURTH;
    private static final DemoEnum ENUM$VALUES[];
    static {
        SPRING = new T("FIRST", 0);
        SUMMER = new T("SECOND", 1);
        AUTUMN = new T("THIRD", 2);
        WINTER = new T("FOURTH", 3);
        ENUM$VALUES = (new T[] {
        	FIRST, SECOND, THIRD, FOURTH
        });
    }
}

我们可以看到,这个类是final的,不可被继承,并且继承了Enum。并且这个类中的属性和方法都是static的,在类被加载之后初始化。虚拟机在加载类的时候,使用了ClassLoader的loadClass方法,这个方法使用了同步代码块保证了线程安全。

序列化对单例的破坏(非枚举)

序列化会通过反射调用无参数的构造方法创建一个新的对象

下面我们来具体解释一下,

写个测试类:

public class Singleton implements Serializable{
	private final static Singleton INSTANCE  = new Singleton();
	private Singleton(){};
	public static Singleton getInstance(){return INSTANCE;}
	
	public static void main(String[] args) 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值