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;
    }
}

 

posted @ 2021-07-10 17:02  一拳超人的逆袭  阅读(27)  评论(0编辑  收藏  举报