概述
确保单例类只能创建自己的唯一实例 ,并向外提供该实例 唯一实例节省系统创建销毁实例时间,减少内存开销
饿汉式(类加载时实例化)
1.代码实现
public class Hungry {
private static Hungry instance = new Hungry ( ) ;
private Hungry ( ) { }
public static Hungry getInstance ( ) {
return instance;
}
}
2.缺点
可能造成空间浪费(一上来就加载这个类),所以出现懒汉式
懒汉式(使用时实例化)
1.普通懒汉式
class Singleton {
private static Singleton instance;
private Singleton ( ) { }
public synchronized static Singleton getInstance ( ) {
if ( instance== null ) {
instance = new Singleton ( ) ;
}
return instance;
}
}
2.双重检查锁单例模式
class Singleton {
private volatile static Singleton instance;
private Singleton ( ) { }
public static Singleton getInstance ( ) {
if ( instance== null ) {
synchronized ( Singleton . class ) {
if ( instance== null ) {
instance = new Singleton ( ) ;
}
}
}
return instance;
}
}
静态内部类
class Singleton {
private Singleton ( ) { }
public static class InnerClass {
private static final Singleton instance = new Singleton ( ) ;
}
public static Singleton getInstance ( ) {
return InnerClass . instance;
}
}
解决反射破坏单例模式问题
通过反射可以破环以上所有的安全性 破环双重检查锁单例模式为例
class Singleton {
private volatile static Singleton instance;
private Singleton ( ) { }
public static Singleton getInstance ( ) {
if ( instance== null ) {
synchronized ( Singleton . class ) {
if ( instance== null ) {
instance = new Singleton ( ) ;
}
}
}
return instance;
}
}
1.问题1
问题描述 :分别两次获取单例,第一次通过getInstance获取,第二次通过反射newInstance获取解决 :在构造方法中再一层锁进行判断
class Singleton {
private volatile static Singleton instance;
private Singleton ( ) {
synchronized ( Singleton . class ) {
if ( instance!= null ) {
throw new RuntimeException ( "不要试图通过反射破坏单例模式" ) ;
}
}
}
public static Singleton getInstance ( ) {
if ( instance== null ) {
synchronized ( Singleton . class ) {
if ( instance== null ) {
instance = new Singleton ( ) ;
}
}
}
return instance;
}
}
缺陷 :两次获取实例都通过反射获取怎么办,请看问题2
2.问题2
问题描述 :分别两次获取单例,都通过反射newInstance获取,问题1的解决办法就失效了解决 :在类中加一个标志变量
class Singleton {
private volatile static Singleton instance;
private static boolean flag = false ;
private Singleton ( ) {
synchronized ( Singleton . class ) {
if ( flag== false ) {
flag = true ;
} else {
throw new RuntimeException ( "不要试图通过反射破坏单例模式" ) ;
}
}
}
public static Singleton getInstance ( ) {
if ( instance== null ) {
synchronized ( Singleton . class ) {
if ( instance== null ) {
instance = new Singleton ( ) ;
}
}
}
return instance;
}
}
3.问题3
通过以上发现总是可以通过反射破环单例模式的安全性,阅读源码发现枚举类型不允许被反射破坏 到这里往下看枚举知识(重点啊)
枚举
1.概述
2.反射到底可不可以破环枚举呢(重点)