单例模式-枚举
那么现在再写一种最受欢迎的单例模式,即枚举单例模式。
枚举模式的代码如下:
date是为了测试方便。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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、那么我们可以写一个序列化的栗子进行测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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、写一个反射攻击的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 可以看到枚举没有无参构造器,而且仅有一个传两个参数的构造器,如下所示。那么我们就将这两个参数传进去,再测试。
可以看到又抛了额一个异常,但是可以很清楚的了解到这个异常是说不能反射去创建对象,我们从报错的地方进入源码查看详情。
源码清清楚楚的告诉我们如果是枚举类型,就抛出异常,可见枚举是多么的强大!
想要飞得更高,就该忘记地平线!
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 2025成都.NET开发者Connect圆满结束
2019-04-10 单例模式-懒汉式(双重检验)
2019-04-10 单例模式-懒汉式