1. 饿汉式
public class Single {
private final static Single single = new Single();
private Single() {
}
public Single getSingle() {
return single;
}
}
2.懒汉式
public class LazyMan {
private static LazyMan lazyMan;
private LazyMan() {
}
public static LazyMan getLazyMan() {
if (lazyMan == null) {
lazyMan = new LazyMan();
}
return lazyMan;
}
}
3.DCL懒汉式
public class DCLLazyMan {
private static volatile DCLLazyMan dclLazyMan;
private DCLLazyMan() {
}
public static DCLLazyMan getDclLazyMan() {
if (dclLazyMan == null) {
synchronized (DCLLazyMan.class) {
if (dclLazyMan == null) {
dclLazyMan = new DCLLazyMan();
}
}
}
return dclLazyMan;
}
}
防止反射破环DCL,代码如下:
/**
* DCL懒汉式
* volatile 防止指令重排
* synchronized 加锁保证多线程下只有一个对象
*/
public class DCLLazyMan {
// volatile 防止指令重排
private static volatile DCLLazyMan dclLazyMan;
// 自定义一个变量,防止反射修改
private static boolean tag = false;
private DCLLazyMan() {
// 防止两个对象都用反射创建
synchronized (DCLLazyMan.class){
if (!tag){
tag = true;
}else {
throw new RuntimeException("不要试图反射破环单例");
}
}
}
public static DCLLazyMan getDclLazyMan() {
if (dclLazyMan == null) {
synchronized (DCLLazyMan.class) {
if (dclLazyMan == null) {
dclLazyMan = new DCLLazyMan();
}
}
}
return dclLazyMan;
}
}
4. 枚举
public enum EnumSingle{
INSTANCE;
// MyUser 需要单例的实体类
private MyUser myUser;
EnumSingle(){
this.myUser = new MyUser();
}
public MyUser getMyUser() {
return myUser;
}
// 测试
public static void main(String[] args) {
EnumSingle instance = EnumSingle.INSTANCE;
MyUser myUser1 = instance.getMyUser();
System.out.println(myUser1.hashCode());
EnumSingle instance2 = EnumSingle.INSTANCE;
MyUser myUser2 = instance2.getMyUser();
System.out.println(myUser2.hashCode());
// 尝试反射破坏
Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);
EnumSingle enumSingle = declaredConstructor.newInstance();
System.out.println(enumSingle);
}
}
枚举内部已经处理了反射破坏单例的行为,代码如下:
@CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}