{
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.Enum
的valueOf
方法根据名字查找对象,而不是新建一个新的对象,所以防止了反序列化对单例的破坏。
可以查看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