• 单例模式-枚举


    那么现在再写一种最受欢迎的单例模式,即枚举单例模式。

    枚举模式的代码如下:

    date是为了测试方便。

    public enum  EnumInstance {
        INSTANCE;
        private Object date;
    
        public Object getDate() {
            return date;
        }
    
        public void setDate(Object date) {
            this.date = date;
        }
        public static EnumInstance getInstance(){
            return INSTANCE;
        }
    }
    

    1、那么我们可以写一个序列化的栗子进行测试。

    public class SerivalTest {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            EnumInstance instance = EnumInstance.getInstance();
            instance.setDate(new Object());
            //放文件
            ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("single_file"));
            outputStream.writeObject(instance);
    
            //取文件
            File file = new File("single_file");
            ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file));
            EnumInstance hungrySingleton = (EnumInstance) inputStream.readObject();
    
            System.out.println(instance);
            System.out.println(hungrySingleton);
            System.out.println(instance==hungrySingleton);
        }
    }
    

     结果为:

    怎么样?枚举就是这么强大,那么序列化和反序列化对枚举是怎么处理的呢?首先通过inputStream.readObject()进入,找到readEnum()方法。

    如下:

    是通过类型和name进行获得枚举常量,因为枚举中的name是唯一的,并且对应一个枚举常量,所以2012行拿到的肯定是唯一的常量对象,

    这样呢就没有创建新的对象。维持了这个对象的单例属性。枚举中这个处理方法还是很简单的,而且很容易理解,所以枚举类对于序列化

    这个破坏是不受影响的。

     2、写一个反射攻击的例子。

    public class Testreflection {
        public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            Class object = EnumInstance.class;
            Constructor constructor = object.getDeclaredConstructor();
            constructor.setAccessible(true);
    
            EnumInstance instance = EnumInstance.getInstance();
            EnumInstance newInstance = (EnumInstance) constructor.newInstance();
    
            System.out.println(instance.getDate());
            System.out.println(newInstance.getDate());
            System.out.println(instance.getDate() == newInstance.getDate());
    
         }
        }
    

    看结果:

    表示没有获得无参构造器,那么我们打开源码看一哈。java.lang.enum  可以看到枚举没有无参构造器,而且仅有一个传两个参数的构造器,如下所示。那么我们就将这两个参数传进去,再测试。

     

    可以看到又抛了额一个异常,但是可以很清楚的了解到这个异常是说不能反射去创建对象,我们从报错的地方进入源码查看详情。

    源码清清楚楚的告诉我们如果是枚举类型,就抛出异常,可见枚举是多么的强大!

    想要飞得更高,就该忘记地平线!
  • 相关阅读:
    曾今的代码系列——获取当天最大流水号存储过程
    曾今的代码系列——生产者消费者模式
    利用Microsoft.VisualBasic中TextFieldParser解析器把CSV格式倒入数据库
    曾今的代码系列——自己的分页控件+存储过程实现分页
    ASP.NET那点不为人知的事(四)
    SharePoint下用C#代码上传文档至文档库的子文件夹中
    Entity Framework 4 in Action读书笔记——第四章:使用LINQ to Entities查询:使用函数
    Entity Framework 4 in Action读书笔记——第四章:使用LINQ to Entities查询:预先加载和延迟加载
    这几天Colorbox让我寝食难安
    使用ASP.NET MVC3+EF+Jquery制作文字直播系统(四)——完成篇
  • 原文地址:https://www.cnblogs.com/shenwen/p/12676720.html
Copyright © 2020-2023  润新知