你知道吗?枚举单例模式是世界上最好的单例模式!

{

return id.incrementAndGet();

}

public static final IdGeneratorEnum INSTANCE;

private AtomicLong id;

private static final IdGeneratorEnum $VALUES[];

static

{

INSTANCE = new IdGeneratorEnum(“INSTANCE”, 0);

$VALUES = (new IdGeneratorEnum[] {

INSTANCE

});

}

}

1、JVM级别的线程安全

反编译的代码中可以发现枚举中的各个枚举项都是通过static代码块来定义和初始化的,他们会在类被加载时完成初始化,而Java的类加载由JVM保证线程安全。

2、防止反序列化的破坏

Java的序列化专门对枚举的序列化做了规定,在序列化时,只是将枚举对象的name属性输出到结果中,在反序列化时通过java.lang.EnumvalueOf方法根据名字查找对象,而不是新建一个新的对象,所以防止了反序列化对单例的破坏。

可以查看java.io.ObjectInputStream#readObject验证。readObject判断到枚举类时,调用的了这个方法java.io.ObjectInputStream#readEnum

private Enum<?> readEnum(boolean unshared) throws IOException {

if (this.bin.readByte() != 126) {

throw new InternalError();

} else {

ObjectStreamClass desc = this.readClassDesc(false);

if (!desc.isEnum()) {

throw new InvalidClassException("non-enum class: " + desc);

} else {

int enumHandle = this.handles.assign(unshared ? unsharedMarker : null);

ClassNotFoundException resolveEx = desc.getResolveException();

if (resolveEx != null) {

this.handles.markException(enumHandle, resolveEx);

}

String name = this.readString(false);

Enum<?> result = null;

Class<?> cl = desc.forClass();

if (cl != null) {

try {

Enum<?> en = Enum.valueOf(cl, name);

result = en;

} catch (IllegalArgumentException var9) {

throw (IOException)(new InvalidObjectException("enum constant " + name + " does not exist in " + cl)).initCause(var9);

}

if (!unshared) {

this.handles.setObject(enumHandle, result);

}

}

this.handles.finish(enumHandle);

this.passHandle = enumHandle;

return result;

}

}

}

3、防止反射的破坏

对于反射,枚举类同样有防御措施,反射在通过newInstance创建对象时会检查这个类是否是枚举类,如果是枚举类就会throw new IllegalArgumentException("Cannot reflectively create enum objects");,如下是源码java.lang.reflect.Constructor#newInstance

public T newInstance(Object… initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

if (!this.override) {

Class<?> caller = Reflection.getCallerClass();

this.checkAccess(caller, this.clazz, this.clazz, this.modifiers);

}

if ((this.clazz.getModifiers() & 16384) != 0) {

throw new IllegalArgumentException(“Cannot reflectively create enum objects”);

} else {

ConstructorAccessor ca = this.constructorAccessor;

if (ca == null) {

ca = this.acquireConstructorAccessor();

}

T inst = ca.newInstance(initargs);

return inst;

}

}

五、单例模式存在哪些问题?

单例模式有节省资源、保证结果正确、方便管理等优点&#x

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值