您当前的位置: 首页 >  Java

小志的博客

暂无认证

  • 0浏览

    0关注

    1217博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

java设计模式——Enum枚举单例

小志的博客 发布时间:2020-06-02 22:33:48 ,浏览量:0

目录
    • 一、Enum枚举单例
    • 二、序列化和反序列化枚举单例,查看是否是同一实例
    • 三、序列化和反序列化枚举单例,查看是否是同一对象
    • 四、通过反射机制获取枚举单例对象,查看是否能获取

一、Enum枚举单例

1、 定义一个枚举类

package com.rf.designPatterns.singleton.enumSingleton;

/**
 * @description: 定义一个枚举类
 * @author: xiaozhi
 * @create: 2020-06-01 20:50
 * 枚举类的单例模式
 * 1、序列化和反序列化不会出现多次实例化的情况
 * 2、对于反射攻击也不会存在问题
 * 3、EffecttiveJava书中强烈推荐枚举类单例模式
 */
public enum  EnumInstance {
    //声明一个变量
    INSTANCE;

    //声明一个Object类型的成员变量
    private Object data;

    //setter、getter方法
    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
    //对外暴露的方法。
    public static EnumInstance getInstance(){
        return INSTANCE;
    }
}

二、序列化和反序列化枚举单例,查看是否是同一实例

1、定义一个枚举类

package com.rf.designPatterns.singleton.enumSingleton;

/**
 * @description: 定义一个枚举类
 * @author: xiaozhi
 * @create: 2020-06-01 20:50
 * 枚举类的单例模式
 * 1、序列化和反序列化不会出现多次实例化的情况
 * 2、对于反射攻击也不会存在问题
 * 3、EffecttiveJava书中强烈推荐枚举类单例模式
 */
public enum  EnumInstance {
    //声明一个变量
    INSTANCE;

    //声明一个Object类型的成员变量
    private Object data;

    //setter、getter方法
    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
    //对外暴露的方法。
    public static EnumInstance getInstance(){
        return INSTANCE;
    }
}

2、定义一个序列化和反序列化枚举单例的测试类

package com.rf.designPatterns.singleton.enumSingleton;

import java.io.*;

/**
 * @description: 序列化和反序列化测试类
 * @author: xiaozhi
 * @create: 2020-06-01 21:01
 */
public class Test1 {
    public static void main(String[] args) {
        //序列化
        EnumInstance enumInstance = EnumInstance.getInstance();
        ObjectOutputStream oos=null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("singlton_file"));
            oos.writeObject(enumInstance);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //反序列化
        File file = new File("singlton_file");
        EnumInstance newEnumInstance=null;
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
            newEnumInstance= (EnumInstance) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
        e.printStackTrace();
        }

        System.out.println("序列化之前的对象:"+enumInstance);
        System.out.println("反序列化后的对象:"+newEnumInstance);
        System.out.println(enumInstance==newEnumInstance);
    }
}

3、输出结果如下: 在这里插入图片描述

结论:序列化和反序列化不会出现多次实例化的情况

三、序列化和反序列化枚举单例,查看是否是同一对象

1、定义一个枚举类

package com.rf.designPatterns.singleton.enumSingleton;

/**
 * @description: 定义一个枚举类
 * @author: xiaozhi
 * @create: 2020-06-01 20:50
 * 枚举类的单例模式
 * 1、序列化和反序列化不会出现多次实例化的情况
 * 2、对于反射攻击也不会存在问题
 * 3、EffecttiveJava书中强烈推荐枚举类单例模式
 */
public enum  EnumInstance {
    //声明一个变量
    INSTANCE;

    //声明一个Object类型的成员变量
    private Object data;

    //setter、getter方法
    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
    //对外暴露的方法。
    public static EnumInstance getInstance(){
        return INSTANCE;
    }
}

2、定义一个序列化和反序列化枚举单例的测试类,并且获取实例的时候set一个对象。

package com.rf.designPatterns.singleton.enumSingleton;

import java.io.*;

/**
 * @description: 序列化和反序列化测试类
 * @author: xiaozhi
 * @create: 2020-06-01 21:01
 */
public class Test1 {
    public static void main(String[] args) {
        //序列化
        EnumInstance enumInstance = EnumInstance.getInstance();
        enumInstance.setData(new Object());
        ObjectOutputStream oos=null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("singlton_file"));
            oos.writeObject(enumInstance);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //反序列化
        File file = new File("singlton_file");
        EnumInstance newEnumInstance=null;
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
            newEnumInstance= (EnumInstance) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
        e.printStackTrace();
        }

        System.out.println("序列化之前的对象:"+enumInstance.getData());
        System.out.println("反序列化后的对象:"+newEnumInstance.getData());
        System.out.println(enumInstance.getData()==newEnumInstance.getData());
    }
}

3、输出结果如下: 在这里插入图片描述

结论:序列化和反序列化也不会出现创建不同对象的情况

四、通过反射机制获取枚举单例对象,查看是否能获取

1、定义一个枚举单例类

package com.rf.designPatterns.singleton.enumSingleton;

/**
 * @description: 定义一个枚举类
 * @author: xiaozhi
 * @create: 2020-06-01 20:50
 * 枚举类的单例模式
 * 1、序列化和反序列化不会出现多次实例化的情况
 * 2、对于反射攻击也不会存在问题
 * 3、EffecttiveJava书中强烈推荐枚举类单例模式
 */
public enum  EnumInstance {
    //声明一个变量
    INSTANCE;

    //声明一个Object类型的成员变量
    private Object data;

    //setter、getter方法
    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
    //对外暴露的方法。
    public static EnumInstance getInstance(){
        return INSTANCE;
    }
}

2、定义一个反射攻击获取枚举单例的实例测试类

package com.rf.designPatterns.singleton.enumSingleton;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @description:  定义一个反射攻击获取枚举单例的实例测试类
 * @author: xiaozhi
 * @create: 2020-06-02 22:03
 */
public class Test2 {
    public static void main(String[] args) {
        //反射攻击获取枚举单例的实例
        Class enumInstanceClass = EnumInstance.class;
        try {
            Constructor declaredConstructor = enumInstanceClass.getDeclaredConstructor();
            declaredConstructor.setAccessible(true);
            EnumInstance newEnumInstance = declaredConstructor.newInstance();
            System.out.println(newEnumInstance);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
        e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }



    }
}

3、输出如下图:没有获取到无参构造器报错。 在这里插入图片描述

结论:对于反射攻击无法获取枚举单例实例,所以反射攻击失败。

关注
打赏
1661269038
查看更多评论
立即登录/注册

微信扫码登录

0.0438s