JavaSE进阶之(十六)枚举

十六、枚举

  • 16.1 背景
  • 16.2 枚举类型
  • 16.3 EnumSet 和 EnumMap
    • 01、EnumSet
    • 02、EnumMap

16.1 背景

在 Java 语言中还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组 int 类型的常量,常常用的就是:

public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int AUTUMN = 3;
public static final int WINTER = 4;

看似这样写是没有问题的,但是我们写代码的时候通常都会考虑到它的安全性、易用性和可读性。

首先是安全性。显然,这种模式并不是安全的。就拿上面的例子来说,我们根本无法保证传入值的合法性,在编译期和运行期不知道可能会出现什么情况,这就不符合 Java 程序的类型安全了。

其次是可读性。使用枚举类型的大多数场合都是为了方便得到枚举类型的描述(也就是字符串表达式),如果我们只是单一的打印出来这一组数字,也没有太大的用处。这时如果使用 String 来替代 int 作为常量,也不是不可以的,但是可能会导致性能问题,因为它依赖于字符串的比较操作。

从类型安全和程序可读性两方面考虑,int 和 String 枚举模式的缺点就暴露出来了。这时就引入了一个新的解决方案,就是枚举类型(enum type)

16.2 枚举类型

枚举(enum)是 Java 1.5 时引入的关键字,它标识一种特殊类型的类,继承自 java.lang.Enum,由一组固定的常量组成合法的类型。

新建一个枚举类 Season.java:

/**
 * 季节枚举类
 *
 * @author qiaohaojie
 * @date 2023/3/22  14:07
 */
public enum Season {

    SPRING(1),
    SUMMER(2),
    AUTUMN(3),
    WINTER(4);

    private int code;

    Season(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }
}

其实在这个类中,我们并没有看到有继承关系的,来扒一下反编译后的字节码:

public final class Season extends Enum
{

    public static Season [] values()
    {
        return (Season [])$VALUES.clone();
    }

    public static Season valueOf(String name)
    {
        return (Season )Enum.valueOf(com/qhj/enumtype/Season, name);
    }

    private Season(String s, int i)
    {
        super(s, i);
    }

    public static final int SPRING;
	public static final int SUMMER;
	public static final int AUTUMN;
	public static final int WINTER;
	private static final Season $VALUES[];

    static 
    {
        SPRING= new Season ("SPRING", 0);
        SUMMER= new Season ("SUMMER", 1);
        AUTUMN= new Season ("AUTUMN", 2);
        WINTER= new Season ("WINTER", 3);
        $VALUES = (new Season[] {
            SPRING, SUMMER, AUTUMN, WINTER
        });
    }
}

Java 编译器帮我们做了很多隐式的工作:

  1. 要继承 Enum 类;
  2. 要写构造方法;
  3. 要声明静态变量和数组;
  4. 要用 static 块来初始化静态变量和数组;
  5. 要提供静态方法,比如 values() 和 valueOf(String name)。

作为开发者,我们的代码量减少了,枚举看起来简洁明了。

既然枚举是一种特殊的类,那么它其实是可以定义在一个类的内部的,这样它的作用域就可以限定于这个外部类中使用:

/**
 * 枚举定义在外部类中
 *
 * @author qiaohaojie
 * @date 2023/3/22  22:28
 */
public class SeasonClass {

    private Season season;

    public enum Season {

        SPRING(1),
        SUMMER(2),
        AUTUMN(3),
        WINTER(4);

        private int code;

        Season(int code) {
            this.code = code;
        }

        public int getCode() {
            return code;
        }
    }

    public boolean isSeason() {
        return getSeason() == Season.AUTUMN;
    }

    public Season getSeason() {
        return season;
    }

    public void setSeason(Season season) {
        this.season = season;
    }
}

Season 就相当于 SeasonClass 的内部类。

由于枚举是 final 的,所以可以确保在 Java 虚拟机中仅有一个常量对象,基于这个原因,我们可以使用 “==” 运算符来比较两个枚举是否相等,比如上面的 isSeason() 方法。

至于为什么不用 equals() 方法呢?

  1. 首先,“==” 运算符比较的时候,如果两个对象都为 null,并不会发生 NullPointerException,而 equals() 方法就会发生。
    在这里插入图片描述

  2. 另外,“==” 运算符会在编译时进行检查,如果两侧的类型不匹配,就会提示错误,而 equals() 方法则不会:在这里插入图片描述

另外,枚举还可以用于 switch 语句,和基本数据类型的用法一致:

public static String getChineseSeason(Season season) {
	 StringBuffer result = new StringBuffer();
	 switch (season) {
	     case SPRING:
	         result.append("[中文:春天,枚举常量:" + season.name() + ",数据:" + season.getCode() + "]");
	         break;
	     case SUMMER:
	         result.append("[中文:夏天,枚举常量:" + season.name() + ",数据:" + season.getCode() + "]");
	         break;
	     case AUTUMN:
	         result.append("[中文:秋天,枚举常量:" + season.name() + ",数据:" + season.getCode() + "]");
	         break;
	     case WINTER:
	         result.append("[中文:冬天,枚举常量:" + season.name() + ",数据:" + season.getCode() + "]");
	         break;
 }

如果枚举中需要包含更多信息的话,可以为其添加一些字段,比如:code、name 等,这时就需要为枚举添加一个带参的构造方法,这样就可以在定义枚举时添加对应的名称了。

16.3 EnumSet 和 EnumMap

01、EnumSet

EnumSet 是一个专门针对枚举类型的 Set 接口的实现类,它是处理枚举类型数据的一把利器,非常高效的。从名字上也可以看得出,EnumSet 不仅和 Set 有关系,也和枚举有关系。

因为 EnumSet 是一个抽象类,所以创建 EnumSet 时不能使用 new 关键字,但是 EnumSet 提供了很多有用的静态工厂方法。

举个例子,我们可以使用 noneOf) 静态工厂方法创建一个空的 Season 类型的 EnumSet;使用 allOf() 静态工厂方法创建一个包含所有 Season 类型的 EnumSet:

/**
 * @author qiaohaojie
 * @date 2023/3/22  22:41
 */
public class SeasonClassTest {
    public static void main(String[] args) {
        EnumSet<Season> enumSetNone = EnumSet.noneOf(Season.class);
        System.out.println(enumSetNone); // []

        EnumSet<Season> enumSetAll = EnumSet.allOf(Season.class);
        System.out.println(enumSetAll); // [SPRING, SUMMER, AUTUMN, WINTER]
    }
}

有了 EnumSet 后,就可以使用 Set 的一些方法了:
在这里插入图片描述

02、EnumMap

EnumMap 是一个专门针对枚举类型的 Map 接口的实现类,它可以将枚举常量作为键来使用。EnumMap 的效率甚至比 HashMap 还要高,可以直接通过数组下标(枚举的 ordinal 值)访问到元素。

与 EnumSet 不同的是,EnuMap 不是一个抽象类,所以创建 EnumMap 时可以使用 new 关键字:

/**
 * @author qiaohaojie
 * @date 2023/3/22  22:41
 */
public class SeasonClassTest {
    public static void main(String[] args) {
        EnumMap<Season, String> enumMap = new EnumMap<Season, String>(Season.class);
        enumMap.put(Season.SPRING, "春天");
        enumMap.put(Season.SUMMER, "夏天");
        enumMap.put(Season.AUTUMN, "秋天");
        enumMap.put(Season.WINTER, "冬天");
        System.out.println(enumMap); // {SPRING=春天, SUMMER=夏天, AUTUMN=秋天, WINTER=冬天}
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ElementUI学习笔记

目录 一、简单介绍 二、安装 1、下载 2、引入 三、布局 1、简介 2、使用 3、好处 四、布局容器 1、常见排布 2、调整样式 五、按钮 1、简单引用 2、改变样式 3、加载中效果 六、表格 1、简单使用 2、样式修改 七、对话框 1、简单使用 2、添加自定义内容 3、…

7个最受瞩目的 Python 库,提升你的开发效率

当今时代&#xff0c;数据分析和处理已经成为了各行各业中不可或缺的一环。Python作为一种非常流行的编程语言&#xff0c;为我们提供了许多强大的工具和库来处理不同类型的数据。 在这篇文章中&#xff0c;我将向您介绍七个非常有用的Python库&#xff0c;这些库各自有着独特…

js调用gpt3.5

参考链接&#xff1a;直接在前端调用 GPT-3 API 效果图&#xff1a; <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>ChatGPT Web Example</title><style>body {font-family: "Helvetica Neue"…

TimeQuest时序路径详解

&#x1f4a1; 基于TimeQuest软件来查看时序报告和分析时序路径 分析最坏传输路径 根据[FPGA典型时序路径的分析可知&#xff0c;最坏传输路径对应的建立时间&#xff08;setup time&#xff09;余量最小。所以&#xff0c;查看最坏传输路径也就是查看建立时间余量最小的路径。…

【Linux】安装DHCP服务器

1、先检测网络是否通 get dhcp.txt rpm -qa //查看软件包 rpm -qa |grep dhcp //确定是否安装 yum install dhcp //进行安装 安装完成后 查询 rpm -ql dhcp 进行配置 cd /etc/dhcp 查看是否有遗留dhcpd.conf.rpmsave 删除该文件 cp /usr/share/doc/dhcp-4.1.1/dhcpd.conf.sampl…

ChatGPT能代替Oracle DBA吗?用Oracle OCP(1z0-083)的真题测试一下。

让我们来看看ChatGPT不能通过Oracle OCP的考试&#xff1f; 文章目录引言测试过程总结和分析关于博主&#xff0c;姚远&#xff1a;Oracle ACE&#xff08;Oracle和MySQL数据库方向&#xff09;。Oracle MAA 大师。华为云MVP。《MySQL 8.0运维与优化》的作者。拥有 Oracle 10g和…

mysql和mysql2模块的区别!!(nodejs中的模块)

mysql 和 mysql2 都是 Node.js 中常用的操作 MySQL 数据库的模块&#xff0c;它们的主要区别是在实现方式上略有不同。 mysql&#xff1a;是 Node.js 中比较早期的 MySQL 操作模块&#xff0c;该模块底层使用的是回调函数&#xff08;callback&#xff09;来实现异步操作。在处…

ESP32设备驱动-DHT12温湿度传感器驱动

DHT12温湿度传感器驱动 文章目录DHT12温湿度传感器驱动1、DHT12介绍2、硬件准备3、软件准备4、驱动实现1、DHT12介绍 DHt12是经典DHT11温湿度传感器的升级版&#xff0c;完全向下兼容&#xff0c;精度更高&#xff0c;增加了I2C接口。 DHT12 具有单总线和标准 I 2C 两种通讯&…

一文7个步骤从0到1教你搭建Selenium 自动化测试环境

【导语】Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本。本文详细介绍了搭建自动化测试环境所需的工具&#xff0c;让你学习自动化测试不…

不用科学上网,免费的GPT-4 IDE工具Cursor保姆级使用教程

大家好&#xff0c;我是可乐。 过去的一周&#xff0c;真是疯狂的一周。 GPT-4 震撼发布&#xff0c;拥有了多模态能力&#xff0c;不仅能和GPT3一样进行文字对话&#xff0c;还能读懂图片&#xff1b; 然后斯坦福大学发布 Alpaca 7 B&#xff0c;性能匹敌 GPT-3.5&#xff…

[图像识别]关于cv2库无法安装的故障问题解决,全网最全解决方案!本人亲身测试,参考了stackoverflow、51CTO等博客文章总结而成

本文范畴&#xff1a;故障排查 cv2 技术 库安装 Linux/Unix 笔记本系统&#xff1a;win10 python版本&#xff1a;3.10 故障问题&#xff1a;无法安装cv2库 适应对象&#xff1a;程序员新手、运维程序员、大学生、青少年对系统感兴趣的爱好者等等 文章目录前言一、cv2库是什么&…

【C语言】栈区与堆区

目录分配管理方式申请大小限制不同申请效率不同总结&#xff1a;栈区、堆区 是内存模型 对比起来看 分配管理方式 栈区由编译器自动管理&#xff0c; 函数运行时分配&#xff0c;函数结束时释放。存放为运行函数而分配的局部变量&#xff08;函数结束时&#xff0c;其内临时…

超级实用,解密云原生监控技术,使用prometheus轻松搞定redis监控

前言 大家好&#xff0c;我是沐风晓月&#xff0c;本文收录于《 prometheus监控系列》 &#xff0c;截止目前prometheus专栏已经更新到第8篇文章。 本文中的是prometheus已经安装好&#xff0c;如果你还未安装&#xff0c;可以参考 prometheus安装及使用入门 若你想监控其他…

现代数据栈MDS应用落地介绍—Vero营销自动化平台

Dazdata MDS现代数据栈MDS的出现使得中小企业低成本获得大数据处理能力成为可能&#xff0c;技术的进步使得各种基于MDS的大数据应用如雨后春笋般涌现&#xff0c;不同于国内的数据中台更多强调数据处理技术&#xff0c;MDS注重落地和最后一公里的大数据应用。Vero是一款现代数…

1630.等差子数组

1630. 等差子数组 难度中等 如果一个数列由至少两个元素组成&#xff0c;且每两个连续元素之间的差值都相同&#xff0c;那么这个序列就是 等差数列 。更正式地&#xff0c;数列 s 是等差数列&#xff0c;只需要满足&#xff1a;对于每个有效的 i &#xff0c; s[i1] - s[i] …

(五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置

前言 本节内容我们实现虚拟机的克隆&#xff0c;主要根据模板虚拟机克隆三台hadoop虚拟机&#xff0c;用于hadoop集群的搭建&#xff0c;同时根据上一小节的内容&#xff0c;配置hadoop虚拟机的主机名、ip网络等&#xff0c;最终完成hadoop虚拟机的实例化。 正文 虚拟机克隆…

MATLAB | 全网最详细网络图(图论图)绘制教程

一篇超超超长&#xff0c;超超超全面网络图绘制教程&#xff0c;本篇基本能讲清楚所有绘制要点&#xff0c;当然图论与网络优化的算法一篇不可能完全讲清楚&#xff0c;未来如果看的人多可以适当更新&#xff0c;同时做部分网络图绘图复刻。 以下是本篇绘图实验效果&#xff1…

Java中的String类

String类1.String类1.1 特性1.2 面试题1.3 常用方法1.4 String与其他类型之间的转换2. StringBuilder类、StringBuffer类&#xff1a;可变字符序列1.String类 1.1 特性 String类为final类&#xff0c;不可被继承&#xff0c;代表不可变的字符序列&#xff1b; 实现了Serializ…

webpack——使用、分析打包代码

世上本无nodejs js最初是在前端浏览器上运行的语言&#xff0c;js代码一旦脱离了浏览器环境&#xff0c;就无法被运行。直到nodejs的出现&#xff0c;我们在电脑上配置了node环境&#xff0c;就可以让js代码脱离浏览器&#xff0c;在node环境中运行。 浏览器不支持模块化 nodej…

STL—vector

vector介绍在C标准库中&#xff0c;vector是一个常用的序列式容器&#xff08;线性结构&#xff09;&#xff0c;它就好比c语言中的数组&#xff0c;但是vector有一些数组没有的功能&#xff0c;是一个封装好了的类。想要使用vector需要先引入头文件&#xff1a;#include<ve…