Java中的枚举类型

news/2024/10/23 9:39:59/

一,什么是枚举

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

public enum Color {RED,//0BLUE,//1BLACK,//2WHITE;//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);//修改1constructor.setAccessible(true);Color color = (Color) constructor.newInstance("lili",666,5,"YELLOW");//修改2System.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.ppmy.cn/news/1038665.html

相关文章

将Swift Package构建为通用二进制文件 Universal Binary

将Swift软件包构建为通用二进制文件 因此&#xff0c;在苹果在WWDC 2020期间宣布他们将把Mac从英特尔处理器过渡到苹果硅之后&#xff0c;现在是时候让每个人都准备好他们的软件了。 对大多数人来说&#xff0c;这次过渡可能更容易一些&#xff0c;特别是那些已经在iOS上支持a…

如何发布自己的小程序

小程序的基础内容组件 text&#xff1a; 文本支持长按选中的效果 <text selectable>151535313511</text> rich-text: 把HTML字符串渲染为对应的UI <rich-text nodes"<h1 stylecolor:red;>123</h1>"></rich-text> 小程序的…

Nginx反向代理技巧

跨域 作为一个前端开发者来说不可避免的问题就是跨域&#xff0c;那什么是跨域呢&#xff1f; 跨域&#xff1a;指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的&#xff0c;是浏览器对javascript施加的安全限制。浏览器的同源策略是指协议&#xff0c;域名…

​亚马逊推出新运输服务,配送时效最长达5天!

亚马逊2023假日高峰期配送费用出炉&#xff01; 亚马逊美国站发布公告称亚马逊配送(FBA)的年度假日高峰配送费将于2023年10月15日至2024年1月14日期间适用&#xff0c;亚马逊的平均配送费仍然比其他主要第三方物流提供商的较慢标准运输方式便宜30%&#xff0c;以下是公告内容&…

Oracle/PL/SQL奇技淫巧之Json转表

在Oracle中&#xff0c;有些时候我们需要在一个json文档中查数据 这个时候我们可以通过JSON_TABLE函数来把 json文档 提取成一张可以执行正常查询操作的表 先看JSON_TABLE函数的基础用法&#xff1a; JSON_TABLE(json_data, $.json_path COLUMNS (column_definitions))其中&a…

打造专属照片分享平台:快速上手Piwigo网页搭建

文章目录 通过cpolar分享本地电脑上有趣的照片&#xff1a;部署piwigo网页前言1.Piwigo2. 使用phpstudy网页运行3. 创建网站4. 开始安装Piwogo 总结 &#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x…

学习Vue:组件生命周期

在Vue.js中&#xff0c;组件的生命周期是指组件从创建到销毁的整个过程&#xff0c;而生命周期钩子函数则是在不同阶段执行的函数&#xff0c;允许您在特定时间点添加自定义逻辑。本文将详细介绍组件的生命周期以及常用的生命周期钩子函数。 组件的生命周期 组件的生命周期可以…

安装nodejs

1.下载nodejs的压缩包 https://nodejs.org/download/release/latest-v16.x/ 这个是v16版本的&#xff0c;可以根据自己需求下载对应的版本&#xff1a; https://nodejs.org/download/release/ 2.解压&#xff0c;将nodejs放到固定的路径下 注意&#xff1a;不要包含中文路径 3.…