【单例深思】枚举实现单例原理

Java 枚举实现单例模式,线程安全又优雅! 枚举在序列化和反序列化时,并不会调用构造方法,这就防止了反序列化导致的单例破坏的问题。反编译任何一个枚举类会发现,枚举类里的各个枚举项是是通过static代码块来定义和初始化的(可以见后面3.2节反编译分析单例枚举有分析到这个),它们会在类被加载时完成初始化,而java类的加载由JVM保证线程安全,所以,创建一个Enum类型的枚举是线程安全的。因为存在着指令重排序的优化,第2、3步的顺序是不能保证的,最后的执行顺序可能是1-2-3,也可能是1-3-2,假如执行顺序是1-3-2,我们看看会出现什么问题。 阅读详情
单例的枚举实现在《Effective Java》中有提到,因为其 功能完整、使用简洁、无偿地提供了序列化机制、在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点, 单元素的枚举类型被作者认为是实现Singleton的最佳方法。

其实现非常简单,如下:

public   enum  Singleton {
    INSTANCE;
    private Singleton() {}
}

下面我们用一个枚举实现单个数据源例子来简单验证一下:
声明一个枚举,用于获取数据库连接。

public enum DataSourceEnum {
    DATASOURCE;
    private DBConnection connection = null;
    private DataSourceEnum() {
        connection = new DBConnection();
    }
    public DBConnection getConnection() {
        return connection;
    }
}  

模拟一个数据库连接类:

public class DBConnection { }  

测试通过枚举获取的实例是否相同:

  public   class  Main {
    public static void main(String[] args) {
        DBConnection con1 = DataSourceEnum.DATASOURCE.getConnection();
        DBConnection con2 = DataSourceEnum.DATASOURCE.getConnection();
        System.out.println(con1 == con2);
    }
}

输出结果为:true  结果表明两次获取返回了相同的实例。

下面深入了解一下为什么枚举会满足线程安全、序列化等标准。

在JDK5 中提供了大量的语法糖,枚举就是其中一种。
所谓  语法糖(Syntactic Sugar) ,也称糖衣语法,是由英国计算机学家 Peter.J.Landin 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是但是更方便程序员使用。只是在编译器上做了手脚,却没有提供对应的指令集来处理它。

就拿枚举来说,其实Enum就是一个普通的类,它继承自 java.lang.Enum类。

public   enum  DataSourceEnum {
    DATASOURCE;
}  

把上面枚举编译后的字节码反编译,得到的代码如下:

public final class DataSourceEnum extends Enum<DataSourceEnum> {
      public static final DataSourceEnum DATASOURCE;
      public static DataSourceEnum[] values();
      public static DataSourceEnum valueOf(String s);
      static {};
}

由反编译后的代码可知, DATASOURCE  被声明为  static  的, 根据 在 【单例深思】饿汉式与类加载 中所描述的类加载过程,可以知道 虚拟机会保证一个类的 <clinit>()  方法在多线程环境中被正确的加锁、同步。所以,枚举 实现是在 实例化时是线程安全 。

接下来看看序列化问题:

Java规范中规定, 每一个枚举类型极其定义的枚举变量在JVM中都是唯一的,因此在枚举类型的序列化和反序列化上,Java做了特殊的规定。
在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过 java.lang.Enum 的 valueOf() 方法来根据名字查找枚举对象。
也就是说,以下面枚举为例,序列化的时候只将  DATASOURCE  这个名称输出,反序列化的时候再通过这个名称,查找对于的枚举类型,因此反序列化后的实例也会和之前被序列化的对象实例相同。

public   enum  DataSourceEnum {
    DATASOURCE;
}  

由此可知,枚举天生保证序列化单例。


深思S4精锐E加密狗信息修改工具:原理、实现与安全实践 软件授权管理是软件版权保护的核心环节,其原理是通过硬件或软件机制控制软件的使用权限,确保开发者的知识产权和商业利益。在工业软件、财务系统等专业领域,硬件加密狗(如深思HASP系列)因其高安全性而被广泛应用,它通过内置安全芯片存储密钥与授权数据,实现可靠的许可验证。这项技术的核心价值在于为软件提供灵活、可控的授权分发与管理能力,有效应对版本迭代、资产重组等实际业务需求。在实际应用中,用户常面临驱动兼容性(如hasp加密狗驱动在Win10/Win11的安装)、设备识别(如加密狗未检测到或检测异常)以及授权信息维 阅读详情

相关推荐

关于调用深思API读写加密狗

工作中需要完成一些加密狗的简单功能,现稍作记录。 1.加密狗登录与登出1)登录2)登出2.加密狗信息读取与写入1)读取2)写入 1.加密狗登录与登出 1)登录 2)登出 2.加密狗信息读取与写入 1)读取 2)写入 ...

weixin_45482816的博客 3396

全网最简单的Java设计模式【七】枚举实现单例设计模式

枚举实现单例模式的原理基于枚举的特性:每个枚举项都是 public static final 的,因此枚举天然就是单例的。枚举类型在Java中是一种特殊的类,它们不能被继承,也不能有显式的构造函数。这些特性使得枚举成为实现单例模式的理想选择。

技术管理修行 1418

Java高手速成 | 单例模式实现方式——枚举

在Java语言中,如果综合考虑线程安全和延迟加载,IoDH(Initialization Demand Holder)无疑是一种比较好的实现方式,它巧妙利用了Java静态内部类的特点。但是,IoDH的实现方式也存在一些问题。 那么,除了IoDH外,在Java语言中还有没有更好的单例模式实现方法呢? 答案是肯定的。

不断学习,不断进步,提高自己 1140

最安全的单例模式:枚举单例模式(Java)

最安全的单例模式:枚举单例模式(Java) 话不多说,直接上代码: Java public class InstanceDemo { /** * 构造方法私有化 */ private InstanceDemo(){ } /** * 返回实例 * @return */ public stat...

日月星辰的博客 5302

告别Root!用Python脚本一键解密Android微信EnMicroMsg.db数据库(附完整源码)

本文详细介绍了如何在非Root环境下使用Python脚本一键解密Android微信EnMicroMsg.db数据库。通过ADB调试接口和SQLCipher技术,实现自动化提取和解密微信聊天记录数据库,无需Root权限,适合数据分析师和普通用户安全备份数据。

weixin_29266007的博客 329

实战:GMTSAR软件处理陆探一号SAR数据

摘要:陆探一号(LT-1)是我国首组L波段差分干涉SAR卫星星座,具备全天候多极化成像能力,主要服务于自然资源监测等领域。文章详细介绍了其轨道参数(607km太阳同步轨道)和传感器技术指标(5种成像模式)。同时阐述了开源InSAR处理软件GMTSAR的安装方法(基于Ubuntu系统)及实验流程,包括数据准备、DEM生成和干涉处理步骤,特别说明了轨道数据缺失时的MATLAB插值处理方法。该研究为国产SAR卫星数据处理提供了技术参考。

一个RSer的博客 1032

枚举实现单例模式的原理

单例的枚举实现在《Effective Java》中有提到,因为其功能完整、使用简洁、无偿地提供了序列化机制、在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点,单元素的枚举类型被作者认为是实现Singleton的最佳方法。 其实现非常简单,如下: publicenumSingleton{ INSTANCE; privateSingleton(){} } ...

maso88的专栏 4181

ENVI 5.6保姆级教程:高分七号DLC影像从打开到融合的完整流程(附避坑指南)

本文详细介绍了ENVI 5.6处理高分七号DLC影像的完整流程,包括环境准备、数据解压、正射校正、图像融合等关键步骤。特别针对国产卫星数据处理的独特挑战,提供了实用的避坑指南和优化技巧,帮助用户高效完成光学影像的预处理和质量提升。

weixin_33269743的博客 381

【java 基础】枚举深思之反编译枚举类,验证枚举实现单例是线程安全的

1、

李光 未来科技 445

Linux系统监控实战:夜莺监控+categraf采集器配置全流程(附常见问题排查)

本文详细介绍了在Linux系统中使用夜莺监控和categraf采集器进行系统监控的全流程配置,包括环境准备、核心配置文件(如config.toml和procstat.toml)详解、服务集成与验证、高级监控配置实战以及常见问题排查。通过实战案例和优化建议,帮助运维人员快速构建高效的监控体系。

xray4的博客 734

手把手教你用AppsFlyer SDK实现延迟深度链接(附Android/iOS代码示例)

本文详细介绍了如何使用AppsFlyer SDK实现延迟深度链接,提供Android和iOS双平台代码示例,帮助开发者解决跨平台精准跳转与用户归因问题。通过实战案例和高级场景分析,提升应用的用户转化率和广告投放效果。

sre5engineer的博客 694

springboot 单例_如何实现一个单例及优化

前言社长,一个爱学习,爱分享的程序猿,始终相信,付出总会有回报的。知识改变命运,学习成就未来。爱拼才会赢!程序猿学社的GitHub,已整理成相关技术专刊,欢迎Star:。https://github.com/ITfqyd/cxyxs社长,4年api搬运工程师,之前做的都是一些框架的搬运工作,做的时间越长,越发感觉自己技术越菜,有同感的社友,可以在下方留言。现侧重于java底层学习和算法结构学习,希...

weixin_39805998的博客 2641

DMA学习笔记

DMA(direct memory access,直接内存访问),是一种避开CPU,可以直接对外设和内存进行访问的技术,可以实现外设与内存、内存之间、外设之间的数据的访问和搬移。

weixin_46220498的博客 3111

枚举实现单例原理:线程安全及发序列化依旧为单例原因

单例的枚举实现在《Effective Java》中有提到,因为其功能完整、使用简洁、无偿地提供了序列化机制、在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点,单元素的枚举类型被作者认为是实现Singleton的最佳方法。 其实现非常简单,如下: publi...

wangxizzz的博客 687

深入理解 DDR5 Bank Group 与并行调度机制

Bank Group架构和并行调度机制,是DDR5性能跃升的核心秘密!理解它们才能写出高效调度程序,设计出性能强劲又稳定的DDR5系统。🎯记住:Bank Group不是简单的分组,而是高速并行的“魔法钥匙”,巧用它,你的DDR5设计将爆发惊人性能!

weixin_43199439的博客 311

告别手动读摘要!爬虫+大模型做学术助手:爬知网论文,10秒生成摘要+关键词(附完整代码)

知网的官方摘要往往冗长(200-300字),关键词可能不够精准,用大模型提炼“100字精简摘要”和“3-5个核心关键词”,更适合快速筛选文献。这套学术助手的核心价值,是把“找论文、读摘要、提关键词”这些重复劳动,交给爬虫和大模型自动化完成,让科研人从繁琐的文献整理中解放出来,把时间花在实验设计、数据分析等核心工作上。需要注意的是:爬取知网论文仅用于个人科研和学习,不得用于商业用途,遵守知网的用户协议和版权规定;大模型生成的摘要和关键词需后续核对原文,确保准确性。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1942

枚举实现单例原理

单例的枚举实现在《Effective Java》中有提到,因为其功能完整、使用简洁、无偿地提供了序列化机制、在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点,单元素的枚举类型被作者认为是实现Singleton的最佳方法。其实现非常简单,如下:public enum Singleton {    INSTANCE;    private Singleton() {}}下面我们用一个枚...

幻听 825

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

《面试宝典》二 如何实现一个单例及优化

前言: 社长,4年api搬运工程师,之前做的都是一些框架的搬运工作,做的时间越长,越发感觉自己技术越菜,有同感的社友,可以在下方留言。现侧重于java底层学习和算法结构学习,希望自己能改变这种现状。 为什么大厂面试,更侧重于java原理底层的提问,因为通过底层的提问,他能看出一个人的学习能力,看看这个人的可培养潜力。随着springboot的流行,大部分的开发,起步就是springboot。也不...

程序猿学社的博客 5142

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

用枚举实现单例模式的原理(转)

单例的枚举实现在《Effective Java》中有提到,因为其功能完整、使用简洁、无偿地提供了序列化机制、在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点,单元素的枚举类型被作者认为是实现Singleton的最佳方法。 其实现非常简单,如下: public enum Si...

qq_34940489的博客 602

Java枚举类

Java枚举类 为什么引用枚举类 引入枚举类是为了在程序中更方便地定义一组相关的常量。枚举类可以将一组具有相同属性或类型的常量进行封装,使得代码更加清晰、易读,并能提高代码的可维护性和可扩展性。 使用枚举类的好处包括: 清晰明确:枚举类可以为常量赋予一个有意义的名字,使得代码的含义更加清晰明了。 类型安全:枚举类提供了类型安全的保证,避免了传入不合法的参数值。 可维护性:通过使用枚举类,可以集中管理相关的常量,当需要修改或添加新的常量时,只需在枚举类中进行修改即可。 可读性:使用枚举类可以使代码更加易读,

sheep55的博客 1284

java 枚举类详细讲解

有的人说,不推荐使用枚举。有的人说,枚举很好用。究竟怎么使用,如何使用,仁者见仁智者见智。总之,先学会再说~ 为什么要引入枚举类 一个小案例 你写了一个小程序,不过好久不用了,突然有一天,你想使用一下它。程序要想正确运行,需要将今天星期几存到数据库里。这个时候,你开始犯难了。 当初的你还很年轻,不懂程序界的险恶,设计这个程序的时候,傻不拉几把这个字段设计为int类型的,用0代表周日,1代表周一。。。6代表周六,添加的时候就setWeekday(0)。但是这么长时间没用了,你忘记自己是从周一开始计.

weixin_43842087的博客 173
上一篇: 【单例深思】单例与序列化
下一篇: Java new 背着我们干了什么
TaiSung
博客等级 码龄15年 49粉丝 132原创
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值