11.单例模式
1.饿汉式
public class Hungry { //如果有很多占内存的数据的话 饿汉式存在浪费内存的问题,因为一上来就把所有的内存加载完毕了 private byte[] data1=new byte[1024*1024]; //私有化构造器 private Hungry(){ } private final static Hungry HUNGRY=new Hungry(); public static Hungry getInstance(){ return HUNGRY; } }
2.懒汉式
public class Lazy { //私有化构造器 private Lazy(){ } private static Lazy lazy; //存在并发问题 public static Lazy getInstance(){ if(lazy==null){ lazy=new Lazy(); } return lazy; } }
3.双重检测模式的懒汉式
public class Lazy1 { //私有化构造器 private Lazy1(){ } private volatile static Lazy1 lazy; //双重检测锁模式的懒汉式单例 DCL懒汉式 public static Lazy1 getInstance(){ if(lazy==null){ if(lazy==null){ synchronized (Lazy1.class){ if(lazy==null){ /* 1.分配内存空间 2.执行构造方法,初始化对象 3.把这个对象指向这个空间 可能会执行132 所以必须使用volatile关键字禁止指令重排 */ lazy=new Lazy1();//不是原子性操作 } } } } return lazy; } }
4.内部类
public class Holder { private Holder(){} public static Holder getInstance(){ return InnerClass.HOLDER; } public static class InnerClass{ private static final Holder HOLDER=new Holder(); } }
5.利用反射破解双重检测模式的懒汉式
public class Reflection { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Lazy1 lazy1=Lazy1.getInstance(); Constructor<Lazy1> constructor=Lazy1.class.getDeclaredConstructor(null);//获得空参构造器 constructor.setAccessible(true);//无视了私有构造器 Lazy1 lazy2=constructor.newInstance(); System.out.println(lazy1==lazy2);//false } }
6.道高一尺魔高一丈环节
懒汉式反击
public class Lazy1 { //私有化构造器 private Lazy1(){ synchronized (Lazy1.class){ if(lazy!=null){ throw new RuntimeException("不要视图使用反射破坏爷的单例类"); } } } private volatile static Lazy1 lazy; //双重检测锁模式的懒汉式单例 DCL懒汉式 public static Lazy1 getInstance(){ if(lazy==null){ if(lazy==null){ synchronized (Lazy1.class){ if(lazy==null){ /* 1.分配内存空间 2.执行构造方法,初始化对象 3.把这个对象指向这个空间 可能会执行132 所以必须使用volatile关键字禁止指令重排 */ lazy=new Lazy1();//不是原子性操作 } } } } return lazy; } }
反射反击
public class Reflection { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //Lazy1 lazy1=Lazy1.getInstance(); Constructor<Lazy1> constructor=Lazy1.class.getDeclaredConstructor(null);//获得空参构造器 constructor.setAccessible(true);//无视了私有构造器 Lazy1 lazy2=constructor.newInstance(); Lazy1 lazy1=constructor.newInstance(); System.out.println(lazy1==lazy2);//false } }
饿汉式反击
public class Lazy1 { // private static boolean password=false; //私有化构造器 private Lazy1(){ synchronized (Lazy1.class){ if(password==false){ password=true; } else{ throw new RuntimeException("不要视图使用反射破坏爷的单例类"); } } } private volatile static Lazy1 lazy; //双重检测锁模式的懒汉式单例 DCL懒汉式 public static Lazy1 getInstance(){ if(lazy==null){ if(lazy==null){ synchronized (Lazy1.class){ if(lazy==null){ /* 1.分配内存空间 2.执行构造方法,初始化对象 3.把这个对象指向这个空间 可能会执行132 所以必须使用volatile关键字禁止指令重排 */ lazy=new Lazy1();//不是原子性操作 } } } } return lazy; } }
反射反击
public class Reflection { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { //Lazy1 lazy1=Lazy1.getInstance(); Constructor<Lazy1> constructor=Lazy1.class.getDeclaredConstructor(null);//获得空参构造器 constructor.setAccessible(true);//无视了私有构造器 Field password=Lazy1.class.getDeclaredField("password"); password.setAccessible(true); Lazy1 lazy2=constructor.newInstance(); password.set(lazy2,false); Lazy1 lazy1=constructor.newInstance(); System.out.println(lazy1==lazy2);//false } }
点进反射的newInstance源码分析 发现反射不能操作枚举类
没办法破坏的单例
public enum EnumSingle { INSTANCE; public EnumSingle getInstance(){ return INSTANCE; } }