java枚举类2023028

news2024/9/23 21:28:02

一个类的对象是有限而且固定的,比如季节类, 它只有4个对象;再比如行星类,目前只有8个对象。这种实例有限而且固定的类,在Java里被称为枚举类。在早期代码中,可能会直接使用简单的静态常量来表示枚,这种定义方法简单明了,但存在如下几个问题。也就是为啥静态常量定义枚举类为啥不好:
1.类型不安全:因为上面的每个季节实际上是一个int整数,因此完全可以把一个季节当成一个int整数使用,例如进行加法运算SEASON_SPRING+SEASON_SUMMER,这样的代码完全正常。
2.没有命名空间:当需要使用季节时,必须在SPRING前使用SEASON_前缀,否则程序可能与其他类中的静态常量混淆。
3.打印输出的意义不明确:当输出某个季节时,例如输出SEASON_SPRING,实际上输出的是1,这个1很难猜测到它代表了春天。

用普通的类实现枚举类也没问题,因此早期也可采用通过定义类的方式来实现,可以采用如下设计方式。
1.通过private将构造器隐藏起来。
2.把这个类的所有可能实例都使用public static final修饰的类变量来保存。
3.如果有必要,可以提供一些静态方法,允许其他程序根据特定参数来获取与之匹配的实例。
使用枚举类可以使程序更加健壮,避免创建对象的随意性但通过定义类来实现枚举的代码量比较大,实现起来也比较麻烦,Java从JDK 1.5后就增加了对枚举类的支持。Java 5新增了一个enum关键字(它与class、interface关键字的地位相同)用以定义枚举类,枚举类是一种特殊的类,它一样可以有自己的成员变量、方法,可以实现一个或者多个接口,也可以定义自己的构造器。一个Java源文件中最多只能定义一个public访问权限的枚举类,且该Java源文件也必须和该枚举类的类名相同。
但枚举类终究不是普通类,它与普通类有如下简单区别。
1.枚举类可以实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是默认继承Object类,因此枚举类不能显式继承其他父类。其中java.lang.Enum类实现了java.lang.Serializable和java.lang.Comparable两个接口。
2.使用enum定义、非抽象的枚举类默认会使用final修饰。
3.枚举类的构造器只能使用private访问控制符,如果省略了构造器的访问控制符,则默认使用private修饰;如果强制指定访问控制符,则只能指定private修饰符。由于枚举类的所有构造器都是private的,而子类构造器总要调用父类构造器一次,因此枚举类不能派生子类。如果枚举类有子类,子类需要调用枚举类的构造器,但是枚举类的构造器是私有的,不能被调用,则根据逻辑学,推导出枚举类不能有子类。
4.枚举类的所有实例必须在枚举类的第一行显式列出,否则这个枚举类永远都不能产生实例。列出这些实例时,系统会自动添加public static final修饰,无须程序员显式添加。枚举类默认提供了一个values()方法,该方法可以很方便地遍历所有的枚举值。
在这里插入图片描述

枚举类的对象:SeasonEnum.SPRING,同时switch(object),还支持用对象最为判断条件,至少在枚举类这里是支持的!!!
所有的枚举类都继承了java.lang.Enum类,所以枚举类可以直接使用java.lang.Enum类中包含的方法:

  1. int compareTo(E o):该方法用于与指定枚举对象比较顺序,同一个枚举实例只能与相同类型的枚举实例进行比较。如果该枚举对象位于指定枚举对象之后,则返回正整数;如果该枚举对象位于指定枚举对象之前,则返回负整数,否则返回零。
    2.String name():返回此枚举实例的名称,这个名称就是定义枚举类时列出的所有枚举值之一。与此方法相比,大多数程序员应该优先考虑使用toString()方法,因为toString()方法返回更加用户友好的名称。String toString():返回枚举常量的名称,与name方法相似,但toString()方法更常用。
    3.int ordinal():返回枚举值在枚举类中的索引值(就是枚举值在枚举声明中的位置,第一个枚举值的索引值为零)。
    4.public static<T extends Enum> T valueOf(Class enumType,String name):这是一个静态方法,用于返回指定枚举类中指定名称的枚举值。名称必须与在该枚举类中声明枚举值时所用的标识符完全匹配,不允许使用额外的空白字符。
    正如前面看到的,当程序使用System.out.println(s)语句来打印枚举值时,实际上输出的是该枚举值的toString()方法,也就是输出该枚举值的名字。

枚举类也有成员变量,方法,构造器在这里插入图片描述上面程序使用Gender枚举类时与使用一个普通类没有太大的差别,差别只是产生Gender对象的方式不同,用的是Enum.valueOf()方法,枚举类的实例只能是枚举值,而不是随意地通过new来创建枚举类对象。
面临问题:
首先Java应该把所有类设计成良好封装的类,所以不应该允许直接访问Gender类的name成员变量,而是应该通过方法来控制对name的访问。否则可能出现很混乱的情形,例如上面程序恰好 设置了g.name=“女”,要是采用g.name=“男”,那程序就会非常混乱了,可能出现FEMALE代表男的局面。
进一步可以将name设置为private的,然后加个set方法。
进一步优化,枚举类通常应该设计成不可变类,即它的成员变量值不应该允许改变,这样会更安全,且代码更加简洁。因此建议将枚举类的成员变量都使用private final修饰。
成员变量都使用了final修饰符来修饰===》必须在构造器里/定义成员变量/初始化块中时 为这些成员变量指定初始值,因此应该为枚举类显式定义带参数的构造器。
一旦为枚举类显式定义了带参数的构造器,列出枚举值时就必须对应地传入参数。
在这里插入图片描述在这里插入图片描述

当为Gender枚举类创建了一个Gender(String name)构造器之后,在枚举类中列出枚举值时,实际上就是调用这个构造器创建枚举类对象,只是这里无须使用new关键字,也无须显式调用构造器。但是要传入参数了。如上所示。

学生提问:
枚举类不是用final修饰了吗?怎么还能派生子类呢?
答:
并不是所有的枚举类都使用了final修饰!非抽象的枚举类才默认使用final修饰。对于一个抽象的枚举类而言——只要它包含了抽 象方法,它就是抽象枚举类,系统会默认使用abstract修饰,而不是使用final修饰。

那么枚举类中可以定义抽象方法么?可以
假设有一个Operation枚举类,它的4个枚举值PLUS,MINUS,TIMES,DIVIDE分别代表加、减、乘、除4种运算,该枚举类需要定义一个eval()方法来完成计算。
Operation需要让PLUS、MINUS、TIMES、DIVIDE四个值对eval()方法各有不同的实现。此时可考虑为Operation枚举类定义一个eval()抽象方法,然后让4个枚举值分别为eval()提供不同的实现。
在这里插入图片描述编译上面程序会生成5个class文件,其实Operation对应一个class文件,它的4个匿名内部子类分别各对应一个class文件。
枚举类里定义抽象方法时不能使用abstract关键字将枚举类定义成抽象类(因为系统自动会为它添加abstract关键字),但因为枚举类需要显式创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现,否则将出现编译错误。此时
PLUS、MINUS、TIMES、DIVIDE实际上是Operation枚举类的匿名子类的实例,而不是Operation类的实例。当调用MALE和FEMALE两个枚举值的方法时,就会看到两个枚举值的方法表现不同的行为方式。

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

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

相关文章

设计模式 - 六大设计原则之OCP(开闭原则)

文章目录概述Case接口定义接口实现Bad ImplBetter Impl概述 Open-Close Principle 在面向对象编程领域中&#xff0c;开闭原则规定软件中的类、对象、模块和函数对扩展应该是开放的&#xff0c;但对修改是封闭的。 这意味着 应该用抽象定义结构&#xff0c;用具体实现扩展细节…

使用 AJAX+JSON 实现用户查询/添加功能

实现用户查询/添加功能1. 查询功能准备selectAllServlet&#xff1a;brand.html&#xff1a;2. 添加功能addBrand.html&#xff1a;表单&#xff1a;<script&#xff1a;addServlet&#xff1a;1. 查询功能 需求&#xff1a;在onload&#xff08;页面加载完成&#xff09;事…

SSM项目实战【从 0 到 1】:个人博客

文章目录前言一、项目简介二、项目技术栈三、准备工作1、Spring Boot 项目创建2、mybatis 配置3、数据库创建四、基本框架搭建1、实体层&#xff08;model&#xff09;2、控制器层&#xff08;controller&#xff09;3、服务层&#xff08;service&#xff09;4、持久层&#x…

Liunx相关服务无法启动,带你一步一步找出问题和解决问题

liunx服务无法开启的原因有各种各样&#xff0c;首先我们需要找到我们究竟是为什么不能能够开启这个服务&#xff0c;这里我们先要去考虑到的一个非常重要的问题就是我们的防火墙有没有启动&#xff0c;防火墙有没有把我们的要开启相关服务的端口给封禁掉。这个是无论如何都要第…

学习记录668@项目管理之项目沟通管理和干系人管理

书上这部分的内容很无趣、很花里花哨、很杂乱&#xff0c;所以本文只摘取我认为比较有用和有意义的片段。 沟通方式 在发送方自认为已经掌握了足够的信息&#xff0c;有了自己的想法且不需要进一步听取多方意见时&#xff0c;往往选择控制力极强、参与程度最弱的“叙述方式”&a…

ES学习看这一篇文章就够了

第一章 ES简介 第1节 ES介绍 1 2 3 41、Elasticsearch是一个基于Lucene的搜索服务器 2、提供了一个分布式的全文搜索引擎,基于restful web接口 3、Elasticsearch是用Java语言开发的&#xff0c;基于Apache协议的开源项目&#xff0c;是目前最受欢迎的企业搜索引擎 4、Elastics…

机器学习(四):机器学习工作流程

文章目录 机器学习工作流程 一、什么是机器学习 二、机器学习工作流程 1、获取到的数据集介绍 2、数据基本处理 3、特征工程 4、机器学习 5、模型评估 机器学习工作流程 一、什么是机器学习 机器学习是从数据中自动分析获得模型&#xff0c;并利用模型对未知数据进行…

【程序环境和程序预处理】万字详文,忘记了,看这篇就对了

本章介绍一个test.c文件是如何生成一个test.exe文件。首先了解程序环境和程序预处理的大致流程&#xff0c;本章会分别介绍各个流程&#xff0c;但重点是翻译中的编译中的预编译阶段。 文章目录&#xff1a; 1.程序翻译环境和运行环境 1.1程序翻译中的的编译和链接 2.预编译…

Flowable进阶学习(四)任务分配与流程变量

文章目录一、任务分配1. 固定分配2. 表达式分配值表达式&#xff1a;Value expression方法表达式&#xff1a;Method expression3. 监听器分配二、流程变量1. 全局变量2. 局部变量案例&#xff1a;一、任务分配 1. 固定分配 在绘制流程图时或在流程文件中通过Assignee来指定的…

3.2 特征图尺寸计算与参数共享|池化层的作用|整体网络架构|VGG网络架构|残差网络Resnet|感受野的作用

文章目录特征图尺寸计算与参数共享池化层的作用整体网络架构VGG网络架构&#xff08;了解向&#xff0c;背景向&#xff09;残差网络Resnet&#xff08;了解向&#xff0c;背景向&#xff09;感受野的作用特征图尺寸计算与参数共享 给个例子&#xff1a; 如果输入的数据是32323…

GDB的常用命令

GDB是一个调试程序&#xff0c;可以用来调试C/C程序。这个C/C要产生符号表才能使用GDB调用。例如C&#xff1a; g -g source.cppGDB常用命令 首先要生成一个有调试符号的ELF文件&#xff08;exe curable and linkable format),简单点说就是一个带调试符号可执行文件。加-g参数…

client-go实战之八:更新资源时的冲突错误处理

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 系列文章链接 client-go实战之一&#xff1a;准备工作client-go实战之二:RESTClientclient-go实战之三&#xff1a;Clientsetclient-go实战之四&#xff1a;…

matlab控制理论学习

一、求传递函数表达式residue() 1、极点不同的情况 分子和分母的矩阵分别为&#xff1a; >> num[2 5 3 6]; >> den[1 6 11 6]; 使用下列命令&#xff0c;即可对分式进行展开&#xff0c;展开后有多项&#xff0c;每一项的分子一定是数字&#xff0c;而分母则是一个…

mysql底层解析——连接层,包括连接、解析、缓存、引擎、存储等

1、 前言 打算写一个系列的文章&#xff0c;主要是mysql底层解析。 很多时候&#xff0c;程序员对mysql处于频繁使用&#xff0c;但都一知半解的程度&#xff0c;除了会加个索引&#xff0c;貌似也没啥优化的技能了。事实上&#xff0c;mysql能有今日的成就&#xff0c;必然不…

Selenium4新特性-关联定位策略

Selenium 4 引入了关联元素定位策略(Relative Locators)。这种方式主要是应对一些不好定位的元素&#xff0c;但是其周边相关联的元素比较好定位。实现步骤是先定位周边较容易定位的元素&#xff0c;再根据关联元素定位策略定位到想定位的那个元素。如下以具体案例讲解用法。 以…

UDS诊断系列介绍15-FIM模块功能介绍

本文框架1. 系列介绍1.1 FIM模块概述2. FIM相关概念2.1 FID概念2.2 FIM数据结构3. FIM模块作用过程4. Autosar系列文章快速链接1. 系列介绍 UDS&#xff08;Unified Diagnostic Services&#xff09;协议&#xff0c;即统一的诊断服务&#xff0c;是面向整车所有ECU的一种诊断…

English Learning - L1-13 主动脉修饰 (上) 2023.1.16 周一

English Learning - L1-13 主动脉修饰 &#xff08;上&#xff09; 2023.1.16 周一11 主动脉修饰11.1 定语两大核心when 引导的定语从句where 引导的定语从句为什么有时关系词前会有介词到底用 which 还是用 that ?1. 先行词是 all, much, little, few, the one 等不定代词&a…

Java---微服务---SpringCloud(1)

SpringCloud011.认识微服务1.0.学习目标1.1.单体架构1.2.分布式架构1.3.微服务1.4.微服务技术对比1.5.SpringCloud1.6.总结2.服务拆分和远程调用2.1.服务拆分原则2.2.服务拆分示例2.2.1.导入Sql语句2.2.2.导入demo工程2.3.实现远程调用案例2.3.1.案例需求&#xff1a;2.3.2.注册…

如何使用Facebook Insights提升SEO策略

搜索流量是所有网站都必须考虑的重要因素&#xff0c;但如何才能吸引到更多的访问者呢&#xff1f;我们都知道 Google的 SEO算法&#xff0c;那 Google针对搜索流量的算法有哪些&#xff1f;Facebook Insights &#xff08;Facebook Search Engine Insight&#xff09;是一款搜…

基于python个性化推荐购物系统的设计与实现

源码获取&#xff1a;https://www.bilibili.com/video/BV1Ne4y1g7dC/ 一、开发工具及技术 Python3.6.8&#xff0c;Django3&#xff0c;mysql8&#xff0c;navicat数据库管理工具&#xff0c;html页面&#xff0c;javascript脚本&#xff0c;jquery脚本&#xff0c;bootstrap…