Java中的枚举类型

news2024/11/17 7:22:16

一,什么是枚举

在Java中,枚举(Enumeration)是一种特殊的数据类型,它允许我们定义一个固定数量的常量集合。枚举类型在Java中是通过关键字enum来定义的。每个枚举常量都是枚举类型的实例,它们在枚举类型中以逗号分隔。例如:

public enum Color {
    RED,//0
    BLUE,//1
    BLACK,//2
    WHITE;//3
}

注:枚举类型默认值(ordinal)从0开始,往后依次递增1,如果我们自己赋值,例如 BLUE = 4,前面的RED还是0,那么后面的BLAK就会默认赋值为5,往后依次递增。

但是我们明明可以使用 static final 来定义一个常量,为什么还要再定义enum类型呢?那是因为使用enum更加安全,例如 public static final int RED = 1,我们认为 RED = 1,也可以认为 1 = RED,但是 1也有可能只是一个整数类型,我们使用这种方法无法分辨,而使用枚举enum就可以避免这种情况,因为RED变成枚举类型了。

二,枚举的使用

2.1 switch语句

枚举类型可以使用switch语句:

public enum Color {
    RED,
    BLUE,
    BLACK,
    WHITE;
   
    public static void main(String[] args) {
        Color color1 = Color.BLUE;
        switch (color1){
            case RED:
                System.out.println("red");
                break;
            case BLUE:
                System.out.println("blue");
                break;
            case BLACK:
                System.out.println("black");
                break;
            case WHITE:
                System.out.println("white");
                break;
        }
    }
}

2.2 enum常用方法

方法说明
values()以数组形式返回枚举类型的所有成员
ordinal()获取枚举成员的索引位置,类似于下标,与上面的ordinal不同
valueOf()将普通字符串转换成枚举实例
compareTo()比较两个枚举成员在定义时的顺序
public enum Color {
    RED,
    BLUE,
    BLACK,
    WHITE;

    public static void main(String[] args) {
        Color[] d = Color.values();
        for(Color x : d){
            System.out.println(x + " " + x.ordinal());
        }
        Color a = Color.valueOf("RED");
        System.out.println(a + " " + a.ordinal);
        //注意ordinal()与ordinal是不一样,前一个是类似于下标,后一个是RED代表的值
        System.out.println(RED.compareTo(BLACK));
    }
}

2.3 enum的构造方法

enum的构造方法默认是私有的,也就是说 我们要添加enum的构造方法也必须是私有的!!

源码中enum只有一个构造方法:

 我们自己提供的构造方法:

public enum Color {
    //因为我们自己提供了构造方法,所以就没有默认构造方法,要添加枚举常量必须如下:
    RED(0,"RED"),
    BLUE(1,"BLUE"),
    BLACK(2,"BLACK"),
    WHITE(3,"WHITE");

    int ordinal;
    String color;

    private Color(int ordinal, String color){//构造方法必须是私有的!!!
        this.color = color;
        this.ordinal = ordinal;
    }
}

2.4 枚举方法的来源

我们上面提到了许多枚举的方法,但是我们创建的枚举类却没有继承任何类,那么这些方法是从哪里来的呢?

我们的第一想法肯定是Object类,毕竟Object类是所有类的父类并且是默认继承的,但是事实上却并非如此,因为我们上面提到了compareTo方法,但是Object类却没有实现comparable接口,所以肯定不是继承了Object类。

实际上Java中的枚举类型(Enum)是一个特殊的类,它隐式地继承了java.lang.Enum,我们上面提到的方法基本来源于它,但是有一个例外,那就是values()方法,那么这个values()究竟是从哪里冒出来的呢?

实际上,values()方法是由编译器自动生成并添加到每个枚举类型中的。它返回一个包含枚举类型中所有枚举值的数组。编译器会自动为每个枚举类型添加以下静态方法:

public static T[] values();

其中,T是枚举类型本身。由于这个方法是在编译时自动生成的,因此它不能在Enum类中定义,而是作为每个枚举类型的一个静态方法存在。

三,枚举与反射

讲了以上内容后,我想问一个问题,我们能不能通过上一篇博客讲的反射来获得枚举的实例呢?理论上可以,接下来我们来试一试:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public enum Color {
    RED(0,"RED"),
    BLUE(1,"BLUE"),
    BLACK(2,"BLACK"),
    WHITE(3,"WHITE");
    int ordinal;
    String color;
    private Color(int ordinal, String color){//构造方法必须是私有的!!!
        this.color = color;
        this.ordinal = ordinal;
    }

}
class Demo{
    public static void main(String[] args) {
        try {

            Class<?> a = Class.forName("Color");

            Constructor<?> constructor 
                    = a.getDeclaredConstructor(int.class,String.class);

            constructor.setAccessible(true);
            Color color = (Color) constructor.newInstance(5,"YELLOW");

            System.out.println(color);

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

但是运行时却报了这样的错误:

 可是我们提供的构造方法确实只有两个参数,为什么会显示没有对应的构造方法呢?还记得上文说我们的枚举类型都是默认继承 java.lang.Enum的,既然继承了父类并且提供了构造方法,我们的子类必须先帮助父类进行构造,那我们在构造方法中添加 super()就可以了吗?不是的,实际上是因为Java在我们提供的枚举构造方法参数的前面自动添加了两个参数:

 也就是说实际上我们的提供的构造方法有四个参数,对原方法进行修改:

    public static void main(String[] args) {
        Class<?> a;
        try {
            a = Class.forName("Color");
            Constructor<?> constructor
                    = a.getDeclaredConstructor(String.class, int.class, int.class, String.class);//修改1
            constructor.setAccessible(true);
            Color color = (Color) constructor.newInstance("lili",666,5,"YELLOW");//修改2
            System.out.println(color);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

但是它又报了如下错误:

 它说我们的 newInstance() 报错,我们来看看newInstance()的源代码:

 它说我们的枚举类型不能使用反射!!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【RP2040】香瓜树莓派RP2040之自定义的短按、双击、长按按键

本文最后修改时间&#xff1a;2022年09月15日 11:02 一、本节简介 本节介绍如何编写一个可以自己选择引脚的短按、双击、长按三种方式的按键驱动。 二、实验平台 1、硬件平台 1&#xff09;树莓派pico开发板 ①树莓派pico开发板*2 ②micro usb数据线*2 2&#xff09;电脑…

【数据结构】 List与顺序表及接口的实现

文章目录 什么是List常见接口介绍线性表顺序表顺序表接口的实现add在末尾新增元素在 pos 位置新增元素判定是否包含某个元素查找某个元素对应的位置获取 pos 位置的元素给 pos 位置的元素设为 value删除第一次出现的关键字key获取顺序表的长度清空顺序表 顺序表的优缺点优点&am…

网络通信原理UDP协议(第五十课)

UDP协议:用户数据包协议,无连接、不可靠,效率高 字段长度描述Source Port2字节标识哪个应用程序发送(发送进程)。Destination Port2字节标识哪个应用程序接收(接收进程)。Length2字节UDP首部加上UDP数据的字节数,最小为8。Checksum2字节覆盖UDP首部和UDP数据,是可…

网络通信原理TCP的四次断开连接(第四十九课)

FIN:发端完成发送任务标识。用来释放一个连接。FIN=1表明此报文段的发送端的数据已经发送完毕,并要求释放连接。 SEQ:序号字段。 TCP链接中传输的数据流中每个字节都编上一个序号。序号字段的值指的是本报文段所发送的数据的第一个字节的序号。 序列号为X ACK :确认号 。 …

【操作系统】24王道考研笔记——第二章 进程与线程

第二章 进程与线程 一、进程与线程 1.进程的概念 程序&#xff1a;是静态的&#xff0c;就是个存放在磁盘里的可执行文件&#xff0c;如&#xff1a;QQ.exe。 进程&#xff1a;是动态的&#xff0c;是程序的一次执行过程&#xff0c;如&#xff1a;可同时启动多次QQ程序 引…

stable diffusion基础

整合包下载&#xff1a;秋叶大佬 【AI绘画8月最新】Stable Diffusion整合包v4.2发布&#xff01; 参照&#xff1a;基础04】目前全网最贴心的Lora基础知识教程&#xff01; VAE 作用&#xff1a;滤镜微调 VAE下载地址&#xff1a;C站&#xff08;https://civitai.com/models…

目录扫描工具—dirsearch使用指南

一&#xff1a;工具简介 dirsearch是一个基于Python3的命令行工具&#xff0c;旨在对web服务器中的目录和文件进行暴力破解&#xff0c;既暴力扫描页面结构&#xff0c;包括网页中的目录和文件。 下载地址&#xff1a; 1&#xff1a; https://github.com/maurosoria/dirsear…

2023河南萌新联赛第(六)场:河南理工大学-L 阴晴不定的大橘学长

2023河南萌新联赛第&#xff08;六&#xff09;场&#xff1a;河南理工大学-L 阴晴不定的大橘学长 https://ac.nowcoder.com/acm/contest/63602/L?&headNavacm 文章目录 2023河南萌新联赛第&#xff08;六&#xff09;场&#xff1a;河南理工大学-L 阴晴不定的大橘学长题…

【RP2040】香瓜树莓派RP2040之仿真调试

本文最后修改时间&#xff1a;2022年08月23日 01:57 一、本节简介 本节以树莓派pico开发板为例&#xff0c;介绍如何使用一个pico作为仿真器&#xff0c;给另一个pico仿真调试代码。 二、实验平台 1、硬件平台 1&#xff09;树莓派pico开发板 ①树莓派pico开发板*2 ②micr…

网络通信原理传输层TCP三次建立连接(第四十八课)

ACK :确认号 。 是期望收到对方的下一个报文段的数据的第1个字节的序号,即上次已成功接收到的数据字节序号加1。只有ACK标识为1,此字段有效。确认号X+1SEQ:序号字段。 TCP链接中传输的数据流中每个字节都编上一个序号。序号字段的值指的是本报文段所发送的数据的第一个字节的…

使用 Ansible Galaxy 安装角色

使用 Ansible Galaxy 安装角色 使用 Ansible Galaxy 和要求文件 /home/curtis/ansible/roles/requirements.yml 。从以下 URL 下载角色并安装到 /home/curtis/ansible/roles &#xff1a; http://rhgls.area12.example.com/materials/haproxy.tar 此角色的名称应当为 balancer …

layui下拉框select 弹出层在最外层

出现问题如图所示 想要的效果是如下 这样的效果只需一行代码就能解决 .layui-layer-page .layui-layer-content{overflow: visible!important;}

生信豆芽菜-差异基因富集分析

网址&#xff1a;http://www.sxdyc.com/enrichmentEnrich 该工具使用R 语言的clusterProfiler包对关键基因集进行GO和KEGG富集分析&#xff0c;注意这个的关键基因集可以是差异基因&#xff0c;WGCNA的module基因&#xff0c;也可以是表型相关的基因集 1、数据准备 准备一个基因…

关于统一事件管理,一定有你想知道的(二)

本文部分内容来源于布博士----擎创科技资深产品专家 哈喽~又见面啦~ 上期内容我们说到了事件以及事件管理&#xff0c;戳这里一键恢复上期精彩内容&#xff1a;关于统一事件管理&#xff0c;一定有你想知道的&#xff08;一&#xff09; 这期主要带大家看看事件管理是怎么运用…

spring官方文档浅翻译(1)

文章目录 IOC容器IOC容器和beans的介绍实例化 BeanBeanFactory&#xff1a;ApplicationContext 容器概述配置元数据实例化容器组合基于xml的配置元数据使用容器 bean的概述命名bean别名的使用 实例化bean构造函数实例化静态工厂实例化实例工厂方法bean 在运行时的实际类型 依赖…

学习笔记|基于Delay实现的LED闪烁|模块化编程|SOS求救灯光|STC32G单片机视频开发教程(冲哥)|第八集:实现LED闪烁(下)

文章目录 2 函数的使用1.函数定义&#xff08;需要带类型&#xff09;2.函数声明&#xff08;需要带类型&#xff09;3.函数调用 3 新建文件&#xff0c;使用模块化编程新建xxx.c和xxx.h文件xxx.h格式&#xff1a;调用头文件验证代码调用&#xff1a;完整的文件结构如下&#x…

使用 RHEL 系统角色

使用 RHEL 系统角色 安装 RHEL 系统角色软件包&#xff0c;并创建符合以下条件的 playbook /home/curtis/ansible/selinux.yml &#xff1a; 在所有受管节点上运行 使用 selinux 角色 将角色配置为以强制执行状态使用SELinux yum install rhel-system-roles.noarch su - curti…

七夕送礼指南:这几款礼物不仅颜值高而且非常实用

七夕又被称为“乞巧节”&#xff0c;相传这一天是牛郎织女一年一度的相会日&#xff0c;所以在这个浪漫的节日里&#xff0c;很有多的恋人也会不远万里来相见&#xff0c;在这个浪漫的日子里&#xff0c;送礼物是表达心意和爱意的重要方式&#xff0c;那么&#xff0c;面对琳琅…

前端练手小项目--自定义时间(html+css+js)

自定义时间 写文章的因 关于要写这篇文章的原因 是记录在工作上遇到的困难需求&#xff0c;是希望能给大家提供一些解决问题的思路 接下来我描述这个需求的多样性&#xff0c;难点在哪。 勾选勾选框开始时间与结束时间默认显示昨天与今天。取消勾选框开始时间与结束时间清空。…

element+vue 表格行拖拽功能

解决方案 使用 sortable.js 步骤一&#xff1a; 安装 npm install vuedraggable步骤二&#xff1a;引入 import Sortable from sortablejs;步骤三&#xff1a; el-table 添加row-key属性&#xff0c;外层包一层 sortableDiv <div class"sortableDiv"> 拖…