1.静态内部类实现
在上一版的时候用的是懒汉和饿汉来做单例模式,如果我们采用静态内部类的话,就可以通过classloader来懒加载单例 用静态内部类实现单例模式:
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
这里有几个需要注意的点:
1.从外部无法访问静态内部类LazyHolder,只有当调用Singleton.getInstance方法的时候,才能得到单例对象INSTANCE。
2.INSTANCE对象初始化的时机并不是在单例类Singleton被加载的时候,而是在调用getInstance方法,使得静态内部类LazyHolder被加载的时候。因此这种实现方式是利用classloader的加载机制来实现懒加载,并保证构建单例的线程安全。
2.反射机制打破单例
//获得构造器
Constructor con = Singleton.class.getDeclaredConstructor();
//设置为可访问
con.setAccessible(true);
//构造两个不同的对象
Singleton singleton1 = (Singleton)con.newInstance();
Singleton singleton2 = (Singleton)con.newInstance();
//验证是否是不同对象
System.out.println(singleton1.equals(singleton2));
代码可以简单归纳为三个步骤:
第一步,获得单例类的构造器。
第二步,把构造器设置为可访问。
第三步,使用newInstance方法构造对象。
最后为了确认这两个对象是否真的是不同的对象,我们使用equals方法进行比较。毫无疑问,比较结果是false。
3.用枚举实现单例模式(最佳):
JVM的enum语法糖会阻止枚举类的私有构造方法,缺点是不能懒加载
enum Color {
RED(1),GREEN(2),BLUE(3);
private int code;
Color(int code){
this.code=code;
}
public int getCode(){
return code;
}
}
####4. 总结:

####5. 补充:
使用枚举实现的单例模式,不但可以防止利用反射强行构建单例对象,而且可以在枚举类对象被反序列化的时候,保证反序列的返回结果是同一对象。
对于其他方式实现的单例模式,如果既想要做到可序列化,又想要反序列化为同一对象,则必须实现readResolve方法。
转自:https://mp.weixin.qq.com/s/AdJI5a4w515SPPI_4gVImA