单例模式有很多实现方法,饿汉、懒汉、静态内部类、枚举类
饿汉式: 类加载就会导致该单实例对象被创建
懒汉式: 类加载不会导致该单实例对象被创建,而是首次使用该对象才会被创建
实现1
问题1: 可能有子类继承父类,覆盖了父类的方法,破坏了单例
问题2: 反序列化的时候会生成新的对象,在单例类中加个固定的方法
public Object readResolve(){
return INSTANCE;
}
问题3: 如果设置为共有,其它的类便可以无限创建对象,就不能设为单例了。 不能防止反射来创建新的实例,反射能够得到构造器对象,设置对象的accessable属性为true,通过暴力反射创建新的实例。
问题4: 静态成员变量初始化的时候创建对象,静态成员变量初始化是在类加载的时候完成的,类加载是由JVM保证线程的安全性。
问题5: 方法可以提供更好的封装性,内部实现一些懒惰的初始化;可以提供对创建单例对象时的更多控制;方法支持泛型。
实现2
问题2: 没有,静态成员变量的线程安全性都是在类加载的时候完成的
问题3: 不能用反射来破坏单例
问题4: 枚举类默认都是实现序列化接口的,但是可以避免反序列化破坏单例,通过父类中的valueOf实现的。
问题5: 枚举单例属于饿汉式
问题6: 枚举类中也可以添加构造方法
实现3
实现4
问题2: 首次调用才加锁创建实例对象,后续通过不为空判断直接返回创建好的对象。
问题3: 防止首次创建对象时多线程重复创建。
实现5
问题1: 通过静态内部类完成懒汉式的创建。类加载本身就是懒惰的,类总是第一次被用到时才会触发类加载操作。
问题2: 类加载时静态成员变量的赋值操作是由JVM来保证线程的安全性。