java枚举类及面试题为什么枚举实现单例模式是安全的?

article/2025/7/11 21:21:46

目录

  • 枚举类
    • 为什么会有枚举类?
    • 枚举类的使用
    • 枚举类的常用方法
      • 枚举的构造
    • 枚举类型能被反射吗?
      • 为什么枚举实现单例模式是安全的?
    • 枚举类的优缺点

枚举类

为什么会有枚举类?

假如说程序中有一些颜色的状态,或者说消息的类型等,在JDK1.5之前,只能用常量来进行表示

public class TestEnum {public static final int RED = 1;public static final int BLACK = 2;public static final int GREEN = 3;public static void main(String[] args) {int num = 1;System.out.println(RED == num);}
}
//true

num不是一个颜色,就与实际不太相符合,于是JDK1.5中引入了枚举类型

enum EnumColor {RED, BLACK, GREEN;public static void main(String[] args) {EnumColor color = EnumColor.BLACK;switch (color) {case RED:System.out.println("红色");break;case BLACK:System.out.println("黑色");break;case GREEN:System.out.println("绿色");break;}}
}
//黑色

枚举类的使用

  • 类的对象只有有限个,确定的(星期,性别,季节…)
  • 当需要定义一组常量
  • 使用enum定义的枚举类默认继承了java.lang. Enum类,因此不能再继承其他类
  • 枚举类的构造器只能使用private权限修饰符
  • 枚举类的所有实例必须在枚举类中显式列出(,分隔结尾)。列出的实例
    系统会自动添加public static final修饰必须在枚举类的第一行声明枚举类对象
  • 枚举不能再类外直接实例化,也不能被继承

如果枚举有参数可以添加对应的构造函数,但要注意:枚举的构造函数默认是私有的。所以不能被继承
枚举就是定义了一些状态或者常见集合,一般不需要单独实例化,用的时候到枚举类中找合适的即可
枚举的构造函数不能使用public和protected修饰。

枚举类的常用方法

方法名称描述
values()以数组形式返回枚举类型的所有成员
ordinal()获取枚举成员的索引位置
valueOf()将普通字符串转换为枚举实例
compareTo()比较两个枚举成员在定义时的顺序
enum EnumColor {RED, BLACK, GREEN;public static void main(String[] args) {// 以数组的方式返回所有的枚举成员EnumColor[] colors = EnumColor.values();// 打印每个枚举成员的索引for(int i = 0; i < colors.length; ++i){System.out.println(colors[i] + ":" + colors[i].ordinal());}// 将字符串GREEN转化为枚举类型EnumColor color1 = EnumColor.valueOf("GREEN");System.out.println(color1);// 在进行转换时,如果有对应的枚举类型则转换,否则抛出IllegalArgumentException
//     EnumColor color2 = EnumColor.valueOf("YELLOW");//定义的枚举类没有YELLOW
//     System.out.println(color2);EnumColor color2 = EnumColor.valueOf("BLACK");//定义的枚举类没有YELLOWSystem.out.println(color2);System.out.println("-------------------------------------");System.out.println("枚举实例的比较");// 注意此处的比较是使用枚举成员的索引来比较了EnumColor black = EnumColor.BLACK;EnumColor red = EnumColor.RED;System.out.println(black.compareTo(red));System.out.println(BLACK.compareTo(RED));System.out.println(RED.compareTo(BLACK));}//结果:RED:0BLACK:1GREEN:2GREENBLACK-------------------------------------枚举实例的比较11-1

枚举的构造

上述枚举类型有一个不太友好的地方是,枚举中只有枚举常量,拿到一个枚举常量后还是不知道其是什么颜色的,因此可以给枚举增加构造函数。

 enum EnumColor {RED("红色", 1), BLACK("黑色", 2), GREEN("绿色", 3);private String color;private int key;// 注意:枚举的构造函数默认是私有的,此处不能增加非private的访问权限进行限制/*public*/EnumColor(String color, int key){this.color = color;this.key = key;}public static EnumColor getEnum(String str){for (EnumColor color : EnumColor.values()){if(color.color.equals(str))return color;}return null;}public static void main(String[] args) {System.out.println(EnumColor.getEnum("红色"));}
}

枚举类型能被反射吗?

不能不能不能!
通过看反射的源码,可以看出反射在通过newInstance创建对象时,会检查该类是否ENUM修饰,如果是则抛出异常,反射失败。
在这里插入图片描述

为什么枚举实现单例模式是安全的?

enum Singleton5 {//枚举类的单例模式INSTANCE;public Singleton5 getInstance(){return INSTANCE;}
}

1、 私有化构造器并不保险,通过反射机制调用私有构造器。而枚举类不能被反射,所以可以防止反射攻击

//模拟反射攻击
class Singleton {//双重校验锁,性能佳线程安全private static Singleton4 instance=null;private Singleton4() {}public static Singleton4 getInstance() {if(instance==null) {synchronized (Singleton4.class) {if (instance==null) {//new对象分为三个操作//分配内存//调用构造方法初始化//赋值instance=new Singleton4();}}}return instance;}
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Singleton s=Singleton.getInstance();Singleton sUsual=Singleton.getInstance();Constructor<Singleton> constructor=Singleton.class.getDeclaredConstructor();constructor.setAccessible(true);Singleton sReflection=constructor.newInstance();System.out.println(s+"\n"+sUsual+"\n"+sReflection);System.out.println("正常情况下,实例化两个实例是否相同:"+(s==sUsual));System.out.println("通过反射攻击单例模式情况下,实例化两个实例是否相同:"+(s==sReflection));
}
//com.lxp.pattern.singleton.Singleton@1540e19d
//com.lxp.pattern.singleton.Singleton@1540e19d
//.lxp.pattern.singleton.Singleton@677327b6
//正常情况下,实例化两个实例是否相同:true
//通过反射攻击单例模式情况下,实例化两个实例是否相同:false

2.避免序列化问题(任何一个readObject方法,不管是显式的还是默认的,它都会返回一个新建的实例,这个新建的实例不同于该类初始化时创建的实例)

枚举类的优缺点

1、优点

枚举常量更简单安全 。
枚举具有内置方法 ,代码更优雅

2. 缺点

不可继承,无法扩展

http://chatgpt.dhexx.cn/article/SjOEG1aQ.shtml

相关文章

什么是枚举?

枚举有两种存在形式&#xff1a; 第一种是计算机编程语言的一种数据类型&#xff0c;enum&#xff0c;即枚举类型。在实际问题中&#xff0c;一些变量的取值被限制在一个有限的范围内&#xff0c;例如&#xff1a;一个星期内只有七天&#xff0c;一年只有十二个月…C语言为此提…

什么是枚举【详解】

本期介绍&#x1f356; 主要介绍&#xff1a;什么是枚举&#xff0c;枚举是如何定义、初始化的&#xff0c;以及枚举到底如何使用&#xff0c;还有枚举这种语法存在的优点有那些&#x1f440;。 文章目录 一、什么是枚举&#x1f356;二、枚举类型的定义&#x1f356;三、枚举…

输入文字后不会自动变长的下划线如何制作

问题&#xff1a;设置下划线时&#xff0c;随着文字增多&#xff0c;下划线延长&#xff0c;出现不对齐的情况 &#xff0c;如下图 解决&#xff1a;制作表格&#xff0c;把不需要的边框删除&#xff0c;就我现在需要的效果&#xff0c;实现步骤如下 制作表格 设置单元格的边距…

CSDN中用Markdown如何给文本加下划线(可延长下划线)

解决 使用<u></u>把文字包起来即可。 演示 <u>下划线</u>&#xff0c;效果&#xff1a; 下划线 如何延长下划线 如果想延长下划线&#xff0c;我们会发现直接打空格是没用的&#xff0c;<u>  下划线   </u>&#xff0c;效果&…

css鼠标划过文字出现往两边延伸的下划线

HTML&#xff1a; <div class"nav"><ul><li><a href"#">Gravit Designer</a></li><li><a href"#">Gravit Klex</a></li></ul></div> CSS&#xff1a; /*导航*/.nav{…

【深入理解JS核心技术】12. 什么是一阶函数

一阶函数是一个不接受另一个函数作为参数并且不返回函数作为其返回值的函数。 const firstOrder () > console.log("I am a first order function!"); 复制代码 函数名 函数名就是指向函数的指针&#xff0c;一个函数可以有多个名称。 function sum(num1, num2) …

一个正经的前端学习 开源 仓库(阶段十九)

低调务实优秀中国好青年 (简介) && 附加答案 中文 | English github.com/webVueBlog/… 一个 ☝️ 正经的前端学习 开源 仓库&#xff0c;启发来自 淘宝大佬 冴羽 &#xff0c;初心做一个真正能帮助到大家的仓库。&#xff08;非常口语化的&#xff0c;手写总结&#x…

【深入理解JS核心技术】1.在 JavaScript 中创建对象的可能方式有哪些?

创建对象的方式&#xff1a; 创建空对象&#xff0c;可以使用Object构造函数。&#xff08;对象构造函数&#xff09; var object new Object(); 复制代码 可以使用Object的create方法通过将原型对象作为参数来创建一个新对象 var object Object.create(null); 复制代码 可以…

一个正经的前端学习 开源 仓库(阶段十七-440)

低调务实优秀中国好青年 (简介) && 附加答案 中文 | English github.com/webVueBlog/… 一个 ☝️ 正经的前端学习 开源 仓库&#xff0c;启发来自 淘宝大佬 冴羽 &#xff0c;初心做一个真正能帮助到大家的仓库。&#xff08;非常口语化的&#xff0c;手写总结&#x…

【深入理解JS核心技术】11. 什么是一级函数

在 Javascript 中&#xff0c;函数是第一类对象。一等函数意味着当该语言中的函数被视为任何其他变量时。 例如&#xff0c;在这种语言中&#xff0c;一个函数可以作为参数传递给其他函数&#xff0c;可以由另一个函数返回&#xff0c;也可以作为一个值分配给变量。例如&#x…

一个正经的前端学习 开源 仓库(每日更新)-698道知识点

低调务实优秀中国好青年 (简介) && 附加答案 中文 | English 一个 ☝️ 正经的前端学习 开源 仓库&#xff0c;养成一个好习惯&#xff0c;遇见更好的 自己。一个人可能走得更快&#xff0c;但一群人会走得更远。&#xff08;非常口语化的&#xff0c;手写总结&#xf…

坚持每一天,不忘初心,正经的前端学习(705)

正经的前端学习 中文 | English 一个 ☝️ 正经的前端学习 开源 仓库&#xff0c;每天进步一点&#xff01;欢迎大家前来讨论&#xff0c;如果觉得对你的学习有一定的帮助&#xff0c;欢迎点个Star &#xff08;此仓库每天都会手动更新&#xff09; &#x1f339; &#x1f339…

VB.net:VB编程语言/VB.net语言编程的简介、IDE安装、学习路线(几十项案例代码实现)之详细攻略

VB.net&#xff1a;VB编程语言/VB.net语言编程的简介、IDE安装、学习路线(几十项案例代码实现)之详细攻略 目录 VB编程语言的简介 1、VB编程语言、VBA编程语言、VBS编程语言、VB.net编程语言对比 2、VB语言对比VB.net语言 (1)、VB6.0之前——.NET Framework 引入之前 (2)、…

vue3手动封装一个点击切换下滑线,事件委托,实现简易选项卡

点击切换下滑线 看看效果 body主要代码&#xff1a; 把点击事件绑定到父元素身上&#xff0c;因为把每个li都绑定一个事件工作量太大了&#xff0c;也不显示&#xff1b;所以利用事件委托 <ul click"disPlay"><li class"wy">网页端</l…

【参赛时间延长】InterSystems技术写作大赛:Python

嗨&#xff0c;开发者们&#xff01;欢迎加入第二届InterSystems技术写作大赛&#xff01; &#x1f40d; InterSystems技术写作大赛&#xff1a;Python &#x1f40d; 6月20日至七月20日 延长至7月31日&#xff0c;在社区撰写一篇利用InterSystems技术使用Python的文章&#x…

关于 Android 中 TabLayout 下划线适配文字长度解析(附清晰详细的源码解析)

温故而知新 坚持原创 请多多支持 一、问题背景 假期在做项目的时候&#xff0c;当时遇到了一个需求就是需要使用 TabLayout ViewPager 来实现一个上部导航栏的动态效果&#xff0c;并且希望下划线的长度等于或者小于导航栏中文字的宽度&#xff0c;当时从网上查询资料的时候是…

2021-4-29 工作记录--CSS-鼠标划过文字时,文字下方出现往两边延伸的下划线 + 鼠标划过文字,文字下面的下划线向中间消失;鼠标离开文字,文字下面的下划线向两边延申出现

一、CSS-鼠标划过文字时&#xff0c;文字下方出现往两边延伸的下划线 方法1&#xff1a; 举例&#xff1a; HTML: CSS: 对应代码&#xff1a; //css鼠标划过文字出现往两边延伸的下划线 .header_l li a, .header_r li:not(:last-child) a {position: relative;padding:…

html+导航栏+点击下划线,html导航栏点击后出现下划线_【Word教程】教你制作输入文字依然对齐的封面下划线......

点击上方“祕技”&#xff0c;关注我们 &#xff5e;助你提升工作技能~ 阅读全文大约需10分钟 在学习和生活中&#xff0c;使用word进行封面制作是很常见的应用场景&#xff0c;而下划线又是封面中不可缺少的元素。 很多同学在制作下划线时采用的是“空格下划线”的方法&#x…

论文封面标题下划线制作

一、问题描述 学校发的模板在填写信息的时候&#xff0c;下划线总是填写多少字就延长多少&#xff0c;文字前后加上空格 &#xff08;这样线是变长的&#xff09;是因为他用了文字下划线法&#xff1b; 二、制作方法 先将文字信息罗列出来 统一调整字符宽度 按照最长的字符长…

你不知道的下划线属性-text-decoration

大家好&#xff0c;我是半夏&#x1f474;&#xff0c;一个刚刚开始写文的沙雕程序员.如果喜欢我的文章&#xff0c;可以关注➕ 点赞 &#x1f44d; 加我微信&#xff1a;frontendpicker&#xff0c;一起学习交流前端&#xff0c;成为更优秀的工程师&#xff5e;关注公众号&…