枚举的使用

背景以及定义

枚举是在jdk1.5以后引入的.主要用途是:将常量组织起来,在这之前表示一组常量通常使用定义常量的方式:

public static final int RED = 1;

public static final int GREEN = 2;

public static final int BLUE = 3;

但是常量举例有不好的地方,例如:可能碰巧有一个数字1,但是他有可能误会为是RED,现在我们可以直接用枚举来进行组织,这样一来,就拥有了类型,枚举类型.而不是普通的整型1.

public enum TestEnum {

        RED, GREEN, BLUE;

}

优点:将常量组织起来统一进行管理

场景:错误状态码,消息类型,颜色的划分,状态基等...

本质:这个是java.lang.Enum的子类,也就是说,自己写的枚举类,就算没有显示的继承Enum,但是其默认继承了这个类.

使用

switch语句

public enum TestEnum {RED, BLACK,GREEN,WHITE;public static void main(String[] args) {TestEnum testEnum = TestEnum.BLACK;switch (testEnum) {case RED:System.out.println("red");break;case BLACK:System.out.println("black");break;case WHITE:System.out.println("white");break;case GREEN:System.out.println("green");break;default:break;}}
}

执行结果:
 

2.常用方法:

 Enum类常用的方法

方法名称描述
values()以数组形式返回枚举类型所有成员
ordinal()获取枚举成员的索引位置
valueOf()将普通字符串转换为枚举实例
compareTo()比较两个枚举类成员在定义时的顺序

示例1:

public enum TestEnum1 {RED, BLACK, GREEN, WHITE;public static void main(String[] args) {TestEnum1[] testEnum1s = TestEnum1.values();for(int i = 0; i < testEnum1s.length; i++) {System.out.println(testEnum1s[i] + " " + testEnum1s[i].ordinal());}System.out.println("======================");System.out.println(TestEnum1.valueOf("GREEN"));}
}

示例2:

public enum TestEnum2 {RED, BLACK, GREEN, WHITE;public static void main(String[] args) {//拿到枚举实例BLACKTestEnum2 testEnum2 = TestEnum2.BLACK;//拿到枚举实例REDTestEnum2 testEnum21 = TestEnum2.RED;System.out.println(testEnum2.compareTo(testEnum21));System.out.println(BLACK.compareTo(RED));}
}

刚刚说过,在Java当中枚举实际上就是一个类.所以我们在定义枚举的时候,还可以这样使用定义和枚举.

重要:枚举的构造方法默认是私有的

public enum TestEnum3 {RED("red", 1), BLACK("black", 2), WHITE("white", 3), GREEN("green", 4);private String name;private int key;/*** 1.当枚举对象有参数后,需要提供相应的构造函数* 2.枚举的构造函数默认是私有的,这个一定要记住* @param name* @param key*/private TestEnum3(String name, int key) {this.name = name;this.key = key;}public static TestEnum3 getEnumKey(int key) {for(TestEnum3 t : TestEnum3.values()) {if(t.key == key) {return t;}}return null;}public static void main(String[] args) {System.out.println(getEnumKey(2));}
}

枚举优点缺点

优点:

1.枚举常量更简单更安全

2.枚举具有内置方法,代码更优雅

缺点:

1.不可继承,无法扩展

 枚举和反射

枚举是否能通过反射,拿到实例对象呢?

我们知道,在反射中,任何的一个类,哪怕是私有的,我们也可以通过反射拿到它的实例对象,那么枚举的构造方法也是私有的,我们是否可以拿到呢?接下来,我们来试验一下.

同样利用上述提供的枚举类来进行举例:

import java.lang.reflect.Constructor;public enum TestEnum3 {RED("red", 1), BLACK("black", 2), WHITE("white", 3), GREEN("green", 4);private String name;private int key;/*** 1.当枚举对象有参数后,需要提供相应的构造函数* 2.枚举的构造函数默认是私有的,这个一定要记住* @param name* @param key*/private TestEnum3(String name, int key) {this.name = name;this.key = key;}public static TestEnum3 getEnumKey(int key) {for(TestEnum3 t : TestEnum3.values()) {if(t.key == key) {return t;}}return null;}public static void reflectPrivateConstructor() {try {Class<?> classStudent = Class.forName("demo5.TestEnum3");//注意传入对应的参数,获得对应的构造方法来构造对象,当前枚举类时提供了两个参数分别是String和intConstructor<?> declaredConstructorStudent = classStudent.getDeclaredConstructor(String.class, int.class);//设置为true后可以修改访问权限declaredConstructorStudent.setAccessible(true);Object objectStudent = declaredConstructorStudent.newInstance("绿色", 666);TestEnum3 testEnum3 = (TestEnum3) objectStudent;System.out.println("获取枚举的私有构造函数" + testEnum3);} catch(Exception e) {e.printStackTrace();}}public static void main(String[] args) {reflectPrivateConstructor();}
}

 输出结果:

上述异常信息是:java.lang.NoSuchMethodException:TestEnum.<init>(java.lang.String, int).

意思就是没有对应的构造方法.但是我们提供的枚举类的构造方法就是两个参数分别为String和int阿.问题出现在哪里?我们知道,所有的枚举类都是默认继承java.lang.Enum,说到继承,继承了什么? 继承了父类除构造函数外的所有东西,并且子类要帮助父类进行构造!而我们写的类,并没有帮助父类进行构造!那意思是,我们要在枚举类里面,提供super吗?不是的,枚举比较特殊,虽然我们写的是两个,但是默认他还添加了两个参数,哪两个参数呢?我们看一下Enum的源码:

protected Enum(String name, int ordinal) {this.name = name;this.ordinal = ordinal;
}

也就是说,我们自己的构造函数有两个参数一个是String一个是int,同时他默认后边还会给两个参数,一个是String, 一个是int.也就是说:我们不仅要写子类新增的两个,还应包含父类提供的两个.

这里我们正确给的是4个参数 :

public static void reflectPrivateConstructor() {try {Class<?> classStudent = Class.forName("demo5.TestEnum3");//注意传入对应的参数,获得对应的构造方法来构造对象,当前枚举类时提供了两个参数分别是String和intConstructor<?> declaredConstructorStudent = classStudent.getDeclaredConstructor(String.class, int.class, String.class, int.class);//设置为true后可以修改访问权限declaredConstructorStudent.setAccessible(true);//前两个是父类参数,后面两个是子类参数Object objectStudent = declaredConstructorStudent.newInstance("父类参数", 666, "子类参数", 888);TestEnum3 testEnum3 = (TestEnum3) objectStudent;System.out.println("获取枚举的私有构造函数" + testEnum3);} catch(Exception e) {e.printStackTrace();}}

此时的运行结果是:

 

他还是报错了.不过这正是我们想要的结果!此时的异常信息显示,是我的一个方法,这个方法是:

newInstance()报错了!没错,问题就是在这里,我们来看一下这个方法的源码,为什么会抛出

java.lang.IllegalArgumentException异常呢>? 

源码显示:

 

是的,枚举在这里被过滤了,你不能通过反射获取枚举类的实例! 

因此,枚举对象是非常安全的,就算通过反射,也是不可以创建一个枚举对象的. 

总结

1.枚举本身就是一个类,其构造方法默认是私有的,且都是继承于java.lang.Enum

2.枚举可以避免反射和序列化问题

3.枚举的优点(简单安全,有内置方法,代码更优雅)与缺点(无法拓展)

面试问题

1.写一个单例模式

class Singleton {private static Object locker = new Object();private static volatile Singleton instance = null;private Singleton() {}public static Singleton getInstance() {if(instance == null) {synchronized (locker) {if(instance == null) {instance = new Singleton();}}}return instance;}
}

2.用枚举实现一个单例模式

public enum TestEnum4 {INSTANCE;public TestEnum4 getInstance() {return INSTANCE;}public static void main(String[] args) {TestEnum4 singleton1 = TestEnum4.INSTANCE;TestEnum4 singleton2 = TestEnum4.INSTANCE;System.out.println("两个实例是否相同: " + (singleton1 == singleton2));}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/225402.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库进阶教学——主从复制(Ubuntu22.04主+Win10从)

目录 一、概述 二、原理 三、搭建 1、备份数据 2、主库配置Ubuntu22.04 2.1、设置阿里云服务器安全组 2.2、修改配置文件 /etc/my.cnf 2.3、重启MySQL服务 2.4、登录mysql&#xff0c;创建远程连接的账号&#xff0c;并授予主从复制权限 2.5、通过指令&#xff0c;查…

043、循环神经网络

之——RNN基础 杂谈 第一个对于序列模型的网络&#xff0c;RNN。 正文 1.潜变量自回归模型 潜变量总结过去的信息&#xff0c;再和当前信息一起结合出新的信息。 2.RNN 循环神经网络将观察作为x&#xff0c;与前层隐变量结合得到输出 其中Whh蕴含了整个模型的时序信息&#xf…

如何使用ArcGIS Pro将Excel表转换为SHP文件

有的时候我们得到的数据是一张张的Excel表格&#xff0c;如果想要在ArcGIS Pro中进行分析或者制图则需要先转换为SHP格式&#xff0c;这里为大家介绍一下转换方法&#xff0c;希望能对你有所帮助。 数据来源 本教程所使用的数据是从水经微图中下载的POI数据&#xff0c;除了P…

Ksher H5页面支付实例指导 (PHP实现)

背景 前两天&#xff0c;公司的项目&#xff0c;为了满足泰国客户的支付需求&#xff0c;要求使用 Ksher (开时支付) 对接任务突然就给了鄙人&#xff0c;一脸懵 … 通过了解客户的使用场景、以及参考官网指导 发现&#xff1a;Ksher支付 最令人满意的便是 —— 提供了便捷的 支…

策略模式(组件协作)

策略模式&#xff08;组件协作&#xff09; 链接&#xff1a;策略模式实例代码 注解 目的 正常情况下&#xff0c;一个类/对象中会包含其所有可能会使用的内外方法&#xff0c;但是一般情况下&#xff0c;这些常使用的类都是由不同的父类继承、组合得来的&#xff0c;来实现…

基于Web的宠物医院信息管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本宠物医院信息管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据…

大一C语言查缺补漏 12.24

遗留问题&#xff1a; 6-1 1 在C语言中&#xff0c;如果要保留小数的话&#xff0c;一定要除以2.0&#xff0c;而不是2。 设整型变量m,n,a,b的值均为1&#xff0c;执行表达式&#xff08;m a>b&#xff09;||(n a<b)后&#xff0c;表达式的值以及变量m和n的值是&#…

虚拟机Windows Server 2012 与ubuntu的安装与布置

介绍虚拟机 虚拟机&#xff08;Virtual Machine&#xff0c;简称VM&#xff09;是一种通过软件模拟的计算机系统&#xff0c;可以在一台物理计算机上同时运行多个独立的操作系统和应用软件。虚拟机将物理计算机的硬件资源&#xff08;如处理器、内存、硬盘等&#xff09;虚拟化…

渗透测试 | php的webshell绕过方法总结

目录 1.php的异或运算 2.通过获取注释去绕过 3.利用字符的运算符 4.通过end函数代替[] 5.通过常量去绕过 6.字符串拼接双美元符 7.通过函数定义绕过 8.通过类定义&#xff0c;然后传参分割 9.多传参方式绕过 10.通过get_defined_functions绕过 本文由掌控安全学院 - …

快速入门学习定时任务框架-xxljob

定时任务框架-xxljob 简介 主要用于分布式任务调度&#xff0c;可以将任务调度和执行分布在多个节点上。它提供了一个集中式的管理平台&#xff0c;支持动态添加、修改、删除任务&#xff0c;以及任务的分片执行&#xff0c;确保任务在分布式环境中的高可用性的一个框架 spr…

SSL证书是什么?为什么需要SSL证书?

什么是SSL证书&#xff1f; SSL&#xff0c;全称为Secure Sockets Layer&#xff0c;是一种用于加密网络通信的协议。SSL证书是由一个可信赖的第三方机构颁发的数字证书&#xff0c;用于确保在用户与服务器之间传输的数据经过加密&#xff0c;保护用户隐私和信息安全。SSL证书…

【新资讯】《网络安全事件报告管理办法(征求意见稿)》正在公开征求意见

近年来网络安全事故频发&#xff0c;造成了不少损失和危害。为了减少网络安全事故的发生&#xff0c;规范网络安全事件的报告&#xff0c;国家互联网信息办公室根据《中华人民共和国网络安全法》等法律法规起草了《网络安全事件报告管理办法&#xff08;征求意见稿&#xff09;…

Qt前端技术:5.QSS

这个是表示QFrame中的pushButton中的子类和它子类的子类都将背景变为red 写成大于的时候表示只有直接的子类对象才会变 这个图中的QGroupBox和QPushButton都是QFrame的直接的子类 这个中的QGroupBox是QFrame的直接的子类但是QPushButton 是QGroupBox的子类&#xff0c;QPushB…

模拟EXCEL排序

7-78 模拟EXCEL排序 分数 25 全屏浏览题目 作者 陈越 单位 浙江大学 Excel可以对一组纪录按任意指定列排序。现请编写程序实现类似功能。 输入格式: 输入的第一行包含两个正整数N(≤105) 和C&#xff0c;其中N是纪录的条数&#xff0c;C是指定排序的列号。之后有 N行&am…

react中使用redux最简单最方便的方式,配合rematch简化操作,5分钟学会

react中使用状态管理的方式也很多&#xff0c;比如redux和mobx等&#xff0c;今天这一片就讲一下redux的入门到熟练使用&#xff0c;主要是要理解它redux的组成有哪些&#xff0c;到怎么创建&#xff0c;和组建中怎么使用三个问题。这里先放上官网文档&#xff0c;不理解的地方…

C语言--直接插入排序【排序算法|图文详解】

一.直接插入排序介绍&#x1f357; 直接插入排序又叫简单插入排序&#xff0c;是一种简单直观的排序算法&#xff0c;它通过构建有序序列&#xff0c;对于未排序的数据&#xff0c;在已排序序列中从后向前扫描&#xff0c;找到相应位置并插入。 算法描述&#xff1a; 假设要排序…

Unity VR Pico apk安装失败:INSTALL_FAILED_UPDATE_INCOMPATIBLE

我的报错&#xff1a; PICO4企业版。安装apk&#xff0c;报错“安装失败。&#xff08;所属的Unity项目打包的apk&#xff0c;被我在同一台pico4安装了20次&#xff09; 调试方法&#xff1a; PIco4发布使用UNITY开发的Vr应用&#xff0c;格式为apk&#xff0c;安装的时候发生…

龙芯杯个人赛串口——做一个 UART串口——RS-232

文章目录 Async transmitterAsync receiver1. RS-232 串行接口的工作原理DB-9 connectorAsynchronous communicationHow fast can we send data? 2.波特率时钟生成器Parameterized FPGA baud generator 3.RS-232 transmitter数据序列化完整代码&#xff1a; 4.RS-232 receiver…

Linux之vim编辑器

目录 vim编辑器 vim编辑器指令 命令模式指令 光标相关 移动光标相关 文本操作 底行模式指令 插入模式 vim配置 vimforcpp 面试官&#xff1a;小伙子&#xff0c;你是用什么环境编写代码的&#xff1f; 小明&#xff1a;vs2019 面试官&#xff1a;小伙子&#xff0c…

基于AT89C51单片机的8位密码锁仿真与实物制作

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/88657969?spm1001.2014.3001.5503 源码获取 C 源码仿真图毕业设计实物制作步骤01 摘要 在日常的生活和工作中, 住宅与部门的安全防范、单位的文件档案、财务报表…