枚举单例是怎么保证线程安全和防止反射的

为什么enum枚举实现单例模式天然线程安全? 定义枚举时使用 enum 和 class 一样, 是 Java 中的一个关键字。 就像 class 对应用一个 Class 类一样, enum 也对应有一个 Enum 类。 通过将定义好的枚举反编译, 我们就能发现, 其实枚举在经过 javac 的编译之后, 会被转换成形如 public final class T extends Enum 的定义。 而且, 枚举中的各个枚举项通过 static 来定义的。 如: public enum T { SPRING,SUMMER,AUTUMN,WINTER; } 阅读详情

枚举单例在Java中具有天然的线程安全性和防止反射攻击的特性,这是由于Java对枚举类型的特殊处理方式。以下是详细解释:

1. 线程安全性

Java 枚举类的特性
  • 类加载机制:枚举类型在Java中是特殊的类,由JVM保证其线程安全性。枚举类在第一次被引用时,会进行类加载和初始化。
  • 类加载过程:类加载过程是线程安全的,JVM确保同一个类只会被加载和初始化一次。
  • 单例实例的创建:枚举类型的每一个实例在类加载时就被初始化,且每个枚举常量在JVM中都是单例。

代码示例

public enum Singleton {
    INSTANCE;

    public void doSomething() {
        // 具体操作
    }
}
执行过程
  1. 枚举类加载:在枚举类 Singleton 第一次被引用时,JVM会加载 Singleton 类。
  2. 枚举实例初始化:在类加载过程中,JVM会创建枚举类型的所有实例。在此例中,INSTANCE 枚举常量会被创建。
  3. 线程安全保证:JVM确保枚举类的加载和实例初始化过程是线程安全的,这意味着多个线程同时访问 Singleton.INSTANCE 时,不会发生竞态条件。

2. 防止反射攻击

Java 枚举类的反射特性
  • 限制反射:Java枚举类型的设计在很大程度上防止了通过反射创建实例。JVM内部对枚举类型的类进行了特殊处理,禁止反射创建枚举实例。

代码示例

import java.lang.reflect.Constructor;

public class ReflectionAttack {
    public static void main(String[] args) {
        try {
            Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor(String.class, int.class);
            constructor.setAccessible(true);
            Singleton singleton = constructor.newInstance("INSTANCE", 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
执行过程
  1. 获取构造函数:通过反射获取枚举类 Singleton 的构造函数。
  2. 尝试创建实例:尝试通过反射调用构造函数创建新实例。
  3. 抛出异常:JVM会抛出 NoSuchMethodException 或 IllegalArgumentException,因为枚举类不允许通过反射创建实例。
抛出异常示例
Exception in thread "main" java.lang.NoSuchMethodException: Singleton.<init>(java.lang.String, int)

总结

线程安全
  • 类加载机制:JVM在加载和初始化类时,保证了类的加载过程是线程安全的。
  • 枚举实例初始化:在类加载时创建枚举实例,且每个枚举常量都是单例,避免了多线程环境中的竞态条件。
防止反射攻击
  • 特殊处理:JVM对枚举类型进行了特殊处理,禁止通过反射创建枚举实例。
  • 抛出异常:尝试通过反射创建枚举实例会抛出异常,防止反射攻击破坏单例模式。

由于这些特性,枚举单例模式在Java中被认为是最安全、最简单的单例实现方式。

Java 枚举实现单例模式,线程安全又优雅! 枚举在序列化和反序列化时,并不会调用构造方法,这就防止了反序列化导致的单例破坏的问题。反编译任何一个枚举类会发现,枚举类里的各个枚举项是是通过static代码块来定义和初始化的(可以见后面3.2节反编译分析单例枚举有分析到这个),它们会在类被加载时完成初始化,而java类的加载由JVM保证线程安全,所以,创建一个Enum类型的枚举是线程安全的。因为存在着指令重排序的优化,第2、3步的顺序是不能保证的,最后的执行顺序可能是1-2-3,也可能是1-3-2,假如执行顺序是1-3-2,我们看看会出现什么问题。 阅读详情

相关推荐

枚举类型为什么是线程安全的?为什么反序列化枚举类型也不会创建新的实例?

枚举类型为什么是线程安全的? 我们定义的一个枚举,在第一次被真正用到的时候,会被虚拟机加载并初始化,而这个初始化过程是线程安全的。而我们知道,解决单例的并发问题,主要解决的就是初始化过程中的线程安全问题。 所以,由于枚举的以上特性,枚举实现的单例是天生线程安全的。 为什么反序列化枚举类型也不会创建新的实例? 枚举类型在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化...

Top5软件工程硕士,先后在京东、字节从事多年Java后端开发、实时和离线大数据开发 4518

java枚举是如何保证线程安全的

关键字enum可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这是一种非常有用的功能。本文将深入分析枚举的源码,看一看枚举是怎么实现的,他是如何保证线程安全的,以及为什么用枚举实现的单例是最好的方式。

白话机器学习 288

【地铁上的设计模式】--创建型模式:单例模式(五)--枚举单例

枚举单例是指使用枚举类型来实现单例模式,它是单例模式中最简单、最安全的一种实现方式。在枚举类型中定义的枚举值只会被实例化一次,即保证了全局唯一的实例,而且实现简单、线程安全、防止反射攻击、支持序列化等。枚举单例是一种非常简单、安全且可靠的单例实现方式。在Java和C#中,枚举类型是天然的单例类型,可以通过定义枚举常量来实现单例。枚举单例不仅避免了线程安全问题,还可以防止反序列化和反射攻击,因此是一种非常优秀的单例实现方式。不过,由于枚举单例的实现方式比较特殊,可能会增加代码的复杂性和理解难度。

喵叔 1053

深入探究单例模式(枚举类防止反射机制的破坏)

引入 volatile的特点: volatile可以保证可见性; 不能保证原子性 由于内存屏障,可以保证避免指令重排的现象产生 面试官:那么你知道在哪里用这个内存屏障用得最多呢? 答:单例模式 单例模式 最重要的特点:构造器私有,单例类的实例对象最多只有一个(也可能没有) 饿汉式、DCL懒汉式、静态内部类 1)饿汉式 饿汉式是最简单的一种单例模式,就是无论在这个类的外部需不需要调用这个对象,都会先创建一个实例。定义一个static方法getInstance(),当需要调用这个对象的时候,可以通过这个st

weixin_47365232的博客 1433

绿标短网址app.10086.cn/xxxxx移动短网址缩短接口网址api调用php方式解析

绿标短网址app.10086.cn/xxxxx 移动网缩短接口网址api调用php方式解析 app.10086.cn是移动网站的接口,可以制作移动网等第三方官方网站域名的任意生成接口,由于是认证企业,可以再抖音 微信 qq等第三方渠道正常打开不拦截提示,第三方网址,头条文章等,效果非常号,这里记录下api接口,纯技术php生成,具体规则可以去抖音的开放平台去申请对应接口 。这里用我php模拟抓包获取方式 GET http://www.app10086cn.cn/?i=app.10068.cnHTTP/1.1

qq_20300095的博客 5907

带你一分钟了解电感与磁珠的区别

在电路设计中会经常使用到电感和磁珠,虽然在电路中的作用有所不同,但它们都属于磁性电子元器件,本文简单介绍下电感和磁珠的区别电感和磁珠电感和磁珠的结构主要由磁性材料金属线圈和外壳组成,具体结构如下图所示:电感磁珠结构图电感其实是金属线圈缠绕在磁芯上,而磁珠是在内部折叠后外围包裹着铁氧体磁性材料。电感器(Inductor)又称扼流器、电抗器、动态电抗器是储能器件,能够把电能转化为磁能而存储起来的元件。磁珠则是能量转换(消耗)器件,将流过他的高频信号以热能的形式消耗掉。

攻城狮鹏哥 1409

单例模式(三)最佳实践枚举单例与ThreadLocal的单例

6.单例模式在springmybatis框架当中的使用如图所示。3.编写ThreadLocalInstance单例模式。5.测试类这里就不写了测试代码都在代码如下当中。6.1spring当中这个类。在mybatis当中使用该类。

热爱码农的平民博客 419

手把手教你用周立功USBCANFD-200U和ZCANPRO软件,从驱动安装到UDS诊断一条龙搞定

本文详细介绍了如何使用周立功USBCANFD-200U硬件和ZCANPRO软件,从驱动安装到UDS诊断的全流程操作指南。涵盖硬件连接、软件配置、CAN通信测试及UDS诊断实战,帮助汽车电子爱好者和工程师快速掌握CAN总线通信技术,实现专业的车辆诊断功能。

weixin_30752699的博客 579

单例模式的枚举实现

单例模式是为了确保某个类只能有唯一的一个全局使用的实例。单例模式的实现方式有、以及。在这些实现方式中,枚举是最优的一种实现方式。枚举实现方式的优点在于:实现方式十分简洁、线程安全,而且最重要的,枚举实现方式能有效防止反序列化和反射对单例模式的破坏。下面一一说明。

m0_66078725的博客 345

sentaurus学习笔记(HFET_pGate_GaN仿真)(五)

`(sdedr:define-constant-profile`和`(sdedr:define-constant-profile-region`命令用于定义并应用一个恒定的活性硼掺杂浓度剖面`"ndop_GaN_gate_const"`到氮化镓栅极层上,其值为`NpGaN_gate`。- `"Oxide"`指定了这一层的材料名称(在这里代表氧化层),而`"nucleation"`是这一层在仿真中的标识名称。- `"GaN"`指定了这一层的材料名称,而`"GaN_gate"`是这一层在仿真中的标识名称。

qq_52640792的博客 940

GlobalBuildingAtlas 建筑物白模数据下载

GlobalBuildingAtlas基于OSM开源数据构建全球建筑物3D白模,提供在线浏览和下载服务。官方资源包括GitHub项目地址和TUM数据库链接,支持行政区划检索建筑物数据。

一醉千秋的专栏 540

java单例类的概念_java中用枚举类实现单例模式详解

枚举单例(Enum Singleton)是实现单例模式的一种新方式,尽管单例模式在java中已经存在很长时间了,但是枚举单例相对来说是一种比较新的概念,枚举这个特性是在Java5才出现的,这篇文章主要讲解关于为什么我们应该使用枚举来实现单例模式,它与传统方式实现的单例模式相比较又有哪些优势?1. 枚举写法简单写法简单这是它最大的优点,如果你先前写过单例模式,你应该知道即使有DCL(double c...

weixin_39784972的博客 148

Linux ARM平台开发系列讲解(摄像头V4L2子系统) 2.12.5 V4L2 control的原理和实现

既然涉及到视频输入,就会有很多与 相关的效果,比如对比度、饱和度、色温、白平衡等等,这些都是通用的、必须的控制项,并且大多数仅需要设置一个整数值即可。 内核中已经为我们提供了这个控制类型的,我们只需要明确自己需要添加什么控制类型,然后将其添加进内核中即可。该部分摄像头代码一半厂家会提供驱动或者相对应的参数,否则没有图像处理知识很难开发出来。 返回总目录...

DSMGUOGUO的博客 1435

java 枚举单例模式_使用枚举实现java单例模式示例代码

使用枚举实现java单例模式示例代码时间:2017-08-30来源:华清远见JAVA学院java单例模式是一种常见的设计模式,使用Java单例模式主要是为了避免实例对象的重复创建,造成不必要的时间和内存开发,确保在Java程序中,某个类只有一个实例存在。Java单例模式实现方式有很多,今天华清Java学院小编和大家分享下使用Java枚举实现单例模式的示例代码。通过使用枚举实现java单例...

weixin_39661881的博客 236

DeepSeek赋能公文写作指南(一)

DeepSeek 的出现,为公文写作领域带来了新的曙光。作为先进的人工智能技术,DeepSeek 以其强大的语言理解与生成能力,能为公文写作提供全方位的支持。它可以快速梳理思路,提供丰富的素材参考,辅助优化语言表达,甚至能根据不同的公文类型和场景,生成极具价值的内容框架。《DeepSeek 赋能公文写作指南》正是基于此背景应运而生。本书旨在帮助公文写作者深入了解并充分利用 DeepSeek 这一强大工具,将其融入到公文写作的各个流程中。

通俗易懂学IT 5484

红绿灯背后的数学:如何用Java算出“黄金绿灯时间“?

本文探讨了城市交通信号灯配时优化的数学原理与Java实现方法。文章首先分析了信号灯配时不合理导致的交通问题,指出精确计算绿灯时长的重要性。核心内容包括:1)基于M/M/1排队模型建立车流量数学模型,通过优化算法最小化总等待时间;2)使用Java实现信号灯优化控制器,采用梯度下降法动态调整绿灯时长。文中提供了完整的Java代码实现,包括信号灯控制器基类和优化控制器类,采用原子类保证线程安全,并详细解释了关键算法原理和实现细节。该方案可为城市智能交通系统提供理论支持和技术实现参考。

墨夶的博客 1345

3.单例模式之注册式(枚举)

写枚举实现之前,先探讨反序列化创建对象问题 引入概念: 序列化:就是把内存中的状态通过转换成字节码的形式,从而转成一个IO流,写入到其他地方(如磁盘,网络IO),实质上是将内存中的状态给永久的保留下来。 反序列化:将已经持久化的字节码内容转换为IO流,通过IO流的读取,获取内容转换为java对象。 package com.going.design.singleton.seriable; import java.io.Serializable; /** * Created by renxf o

编程浪子 421

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

漫画:什么是单例模式?(整合版)

—————  第二天  ————— 单例模式第一版: public class Singleton { private Singleton() {} //私有构造函数    private static Singleton instance

程序员小灰的博客 5862

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

java单例 枚举_使用枚举实现java单例模式

通过枚举实现java中的单例模式,具有一下有点:× 将初始化操作交给jvm,能够保证使用时单例对象已初始化;× 使用方便,通过枚举即可调用。/*** Created by shushanfx on 2015/1/5.* 通过使用enumerate,保证单例。*/public enum Singleton {INSTANCE;private String name = null;private St...

weixin_39579468的博客 134

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java 单例模式中的枚举实现

摘要:Java枚举实现单例模式是最佳实践之一,具有线程安全、防止反射攻击和反序列化破坏等优势。枚举类型由JVM保证唯一性,代码简洁高效。示例通过Singleton.INSTANCE获取唯一实例,验证了实例的唯一性。相比其他实现方式,枚举单例模式更安全可靠,是推荐的单例实现方案。

Shipley_Leo的博客 644

设计模式之单例模式

保证多个线程使用同一个实例。

m0_71896135的博客 98

基于枚举实现单例模式的独特魅力与优势

在设计模式的范畴中,单例模式旨在确保一个类在系统中仅有一个实例,并提供全局访问点。实现单例模式的方法众多,而基于枚举实现的单例模式以其独特的特性脱颖而出,展现出其他方式难以比拟的魅力与优势。

wdfdgygg77的博客 398

单例模式详解(破坏单例)

八种单例模式,以及如何破环

m0_69329684的博客 145

java 基于enum的单例模式的实现,以及浅析如何确保其安全性

提示:如需转载,必须注明本文链接 文章目录前言一、enum是什么?二、使用步骤1.引入库2.读入数据总结 前言 java开发中,我们常用enum实现来单例模式,并且不仅能避免多线程同步问题,而且能确保jvm级别的序列化反序列化的安全性。那么enum类型是如何保证这些呢? 提示:以下是本篇文章正文内容,下面案例可供参考 一、enum是什么? enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性。 在Java中,被 enum 关键字修饰的类型就是枚举类型。形式如下: publ.

CS5686的博客 2026

浅析Java设计模式——单例模式(2)

浅析Java设计模式——单例模式(2)单例模式的实现方法有很多,关于懒汉式基本方法及其双重锁检测的方法,已在上篇文章中进行了介绍。文章链接:浅析Java设计模式——单例模式(1)本次介绍通过饿汉式、静态内部类及枚举的方式来实现单例模式。1.饿汉式public class Singleton{ private static Singleton instance=new Singleton();//单...

zyn_1024的博客 1058
上一篇: 静态内部类实现单例是怎么保证线程安全的
下一篇: ProGuard配置详解
彬_小彬
博客等级 码龄10年 574粉丝 103原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬_小彬

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值