Java开发笔记(五十六)利用枚举类型实现高级常量
前面介绍了联合利用final和static可实现常量的定义,该方式用于简单的常量倒还凑合,要是用于复杂的、安全性高的常量,那就力不从心了。例如以下几种情况,final结合static的方式便缺乏应对之策:
1、虽然常量的名称以大写字母拼写,但是对应的取值基本为1、2、3之类的整数,如果把1、2、3直接写在调用的代码里面,岂不是浑水摸鱼顶替了现有的常量蒙混过关?
2、代码可以从常量名推出对应的常量值,可是反过来并不能从常量值推出对应的常量名,开发者晓得不代表程序也晓得。
3、每个常量只有唯一的数值表达,无法表示更丰富的涵义。比如星期一这个常量,可能包括数字“1”、英文单词“Monday”、中文词语“星期一”这些信息组合,然而final联合static的方式只能表达其中一个信息。
听起来似乎言之有理,可是不用整型常量的话,还有什么常量类型能派上用场呢?其实Java语言在设计之初就考虑到了这种情况,在之前的学习当中,已经出现过类似的处理方案。早在介绍本地日期类型LocalDate的时候,提到获取当前月份的办法是调用日期实例的getMonthValue方法,为啥这里不是调用getMonth方法?原来getMonth方法返回的并非整型数值,而是一个Month类型的月份实例,它属于枚举类型。调用该实例的getValue方法,得到的才是月份数字;调用该实例的name方法,可得到大写英文月份的英文单词。先来看看以下的一段月份测试代码:
// 演示Month类型的调用方式。注意,Month类型是Java自带的一种枚举类型private static void testMonth() {LocalDate date = LocalDate.now();Month month = date.getMonth();System.out.println("month number="+month.getValue()+", month name="+month.name());}
运行以上的测试代码,观察到如下的日志文本:
month number=12, month name=DECEMBER
根据结果发现getValue方法返回了12,且name方法返回了DECEMBER。从中可见Month类型既包含了月份的数字信息,也包括了月份的英文单词,这正是枚举类型相对于普通常量的优势。
所谓枚举,指的是某些同类型常量的有限集合。Java不但提供了Month这种枚举类型,而且允许程序员自己定义新的枚举类型,如同定义类那样。不同的是,类定义使用class来标识,而枚举类型使用enum来标识。最简单的枚举定义只需一个名称列表,就像以下代码这般:
//演示枚举类型的简单定义
public enum Season {// 几个枚举变量之间以逗号分隔SPRING, SUMMER, AUTUMN, WINTER
}
以上代码定义了一种季节枚举Season,它包含了春天SPRING、夏天SUMMER、秋天AUTUMN、冬天WINTER这四个枚举项。四个枚举项既是常量,又都属于Season类型,外部访问它们的格式为“Season.枚举项的名称”。下面是外部访问季节枚举项的代码例子:
// 演示简单枚举类型的调用方式private static void testEnum() {Season spring = Season.SPRING; // 声明一个春天的季节实例Season summer = Season.SUMMER; // 声明一个夏天的季节实例Season autumn = Season.AUTUMN; // 声明一个秋天的季节实例Season winter = Season.WINTER; // 声明一个冬天的季节实例// 枚举类型提供的通用方法主要有两个,// 其中ordinal方法可获得该枚举的序号,toString可获得该枚举的字段名称System.out.println("spring number="+spring.ordinal()+", name="+spring.toString());System.out.println("summer number="+summer.ordinal()+", name="+summer.toString());System.out.println("autumn number="+autumn.ordinal()+", name="+autumn.toString());System.out.println("winter number="+winter.ordinal()+", name="+winter.toString());}
运行上面的测试代码,输出下列的日志信息:
spring number=0, name=SPRING
summer number=1, name=SUMMER
autumn number=2, name=AUTUMN
winter number=3, name=WINTER
结合代码和日志结果,可知枚举项的ordinal方法返回了该枚举所处的序号,toString方法返回了该枚举的常量名称。由于ordinal方法和toString方法是枚举类型enum自带的保留方法,因此无需开发者显式定义即可拿来调用。然而这两个方法毕竟是系统提供的,无法满足丰富多变的个性要求,譬如下列两点需求,简单的枚举类型就无法实现:
1、枚举项的默认序号从0开始计数,但现实生活中很多组合是从1开始计数的。例如一月份对应的数字是1,星期一对应的数字也是1,诸如此类。
2、枚举项的默认名称取的是枚举定义里的列表项名称,但往往更需要中文名称。例如界面上希望展示“春天”而非“SPRING”,希望展示“夏天”而非“SUMMER”,等等。
既然枚举的默认序号与默认名称时常不符合实际情况,这势必要求开发者额外定义新的序号和新的名称。假如说给某个类定义新的属性,那真是易如反掌,可现在待处理的是枚举类型而不是类耶。其实枚举类型enum本来就源自类class,故而完全可以把枚举当作类一样来定义,也就是说,枚举允许定义自己的成员属性、自己的成员方法,乃至自己的构造方法。于是重新定义一个季节枚举,在新的枚举定义中添加序号与名称这两个属性,及其对应的get方法,并补充包含初始化赋值的构造方法。特别注意要在枚举项列表中把每个枚举项都换成携带构造方法的枚举声明,表示该枚举项是由指定构造方法生成的,重写后的季节枚举定义代码示例如下:
//演示枚举类型的扩展定义
public enum SeasonCn {// 在定义枚举变量的同时,调用该枚举变量的构造方法SPRING(1,"春天"), SUMMER(2,"夏天"), AUTUMN(3,"秋天"), WINTER(4,"冬天");private int value; // 定义季节的阿拉伯数字private String name; // 定义季节的中文名称字段// 在构造方法中传入该季节的阿拉伯数字和中文名称private SeasonCn(int value, String name) {this.value = value;this.name = name;}// 获取季节的阿拉伯数字public int getValue() {return this.value;}// 获取季节的中文名称public String getName() {return this.name;}
}
根据新的枚举定义代码,枚举项的序号数值与中文名称如愿换了过来。接着轮到外部调用新的枚举类型,大致流程保持不变,只需将原来的ordinal方法替换为getValue方法,将原来的toString方法替换为getName方法。修改之后的调用代码如下所示:
// 演示扩展枚举类型的调用方式private static void testEnumCn() {SeasonCn spring = SeasonCn.SPRING; // 声明一个春天的季节实例SeasonCn summer = SeasonCn.SUMMER; // 声明一个夏天的季节实例SeasonCn autumn = SeasonCn.AUTUMN; // 声明一个秋天的季节实例SeasonCn winter = SeasonCn.WINTER; // 声明一个冬天的季节实例// 通过扩展而来的getName方法,可获得该枚举预先设定的中文名称System.out.println("spring number="+spring.getValue()+", name="+spring.getName());System.out.println("summer number="+summer.getValue()+", name="+summer.getName());System.out.println("autumn number="+autumn.getValue()+", name="+autumn.getName());System.out.println("winter number="+winter.getValue()+", name="+winter.getName());}
运行上述的调用代码,得到以下的日志结果:
spring number=1, name=春天
summer number=2, name=夏天
autumn number=3, name=秋天
winter number=4, name=冬天
由此可见,经过重新编写的SeasonCn枚举,顺利实现了个性化定制序号和名称的目标。
更多Java技术文章参见《Java开发笔记(序)章节目录》
转载于:https://www.cnblogs.com/pinlantu/p/10349659.html
Java开发笔记(五十六)利用枚举类型实现高级常量相关推荐
- 【Visual C++】游戏开发笔记四十六 浅墨DirectX教程十四 模板测试与镜面特效专场
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8632184 作者:毛星云( ...
- 【Visual C++】游戏开发笔记三十六 浅墨DirectX提高班之四 顶点缓存的逆袭
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8276363 作者:毛星云(浅墨 ...
- 【Visual C++】游戏开发笔记二十六 DirectX 11各组件的介绍 第一个DirectX 11 Demo的创建
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...
- 【Visual C++】游戏开发笔记二十六 DirectX 11各组件的介绍第一个DirectX 11 Demo的创建
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7688515 作者:毛星云 邮箱: h ...
- 【Visual C++】游戏开发笔记二十六 DirectX 11各组件的介绍第一个DirectX 11 Demo的创建...
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7688515 作者:毛星云 邮箱: happ ...
- Android开发笔记(十六)秋千摇摆动画SwingAnimation
上节博主介绍了AlphaAnimation和淡入淡出动画的使用,其实AlphaAnimation只是四种补间动画中的一种.那么为了加深对其他补间动画的理解,我想说说旋转动画RotateAnimatio ...
- 易课寄在线购课系统开发笔记(十六)--完成内容服务系统的工程搭建
首页动态展示分析 内容信息要从数据库中获得. 动态展示分析 内容需要进行分类. 分类下有子分类,需要动态管理. 分类下有内容列表. 单点的内容信息: 有图片 有链接 有标题 有价格 包含大文本类型,可 ...
- java中的多态与继承_【Java学习笔记之十六】浅谈Java中的继承与多态
1. 什么是继承,继承的特点? 子类继承父类的特征和行为,使得子类具有父类的各种属性和方法.或子类从父类继承方法,使得子类具有父类相同的行为. 特点:在继承关系中,父类更通用.子类更具体.父类具有更 ...
- Java学习笔记(十六)—— 开发个小项目(GoBang4.0)
接十二,今天重点搞定简单基础版本的AI下棋. 画个大纲(跟随慢慢开发过程不断完善) 1.用户 两个用户对战 一黑一白 用户可以是人,也可以是AI.对战模式支持人人,人机,机机. 属性 本次比赛执棋颜 ...
最新文章
- 厉害了我的VR!老师们用VR来教历史
- applet操作本地文件
- windows 10 安装和使用中5个常见问题
- MQTT protocol level的处理
- 网易智慧企业 Node.js 实践(3)| 灰度环境和应用监控
- c语言用数组写密码程序,想程序高手求助--用C语言来编辑一个输入密码的程序...
- 如果编程语言是女孩子
- bootstrap到底是用来做什么的(概念)
- json_encode 注意点
- JavaScript和C#通用gb2312和utf8编码解码函数简单实现
- php 小程序回调,微信小程序Promise简化回调实例分享
- 程序语言POJ 2406 Power Strings
- Windows平台安装flutter之初体验(安装教程)
- 你的账户配置为阻止使用计算机,Win10打开软件提示为了对电脑进行保护,已经阻止此应用解决方法...
- 一图秒懂!“天使投资、VC、PE、A轮、B轮、C轮融资”的关系
- 实时数据库:优势和报价
- 京东用了哪些大数据平台产品体系?
- 显示杂谈(1)-Gamma到底是个什么鬼
- 2019-11-29-win10-UWP-Controls-by-function
- 运维(1) Jenkinsfile+Dockerfile+Nginx实现前端Vue自动化部署
热门文章
- 前端框架 Bootstrap 5.0 alpha 发布
- 如何使用Elasticsearch在.NET应用程序中实现全文搜索
- Optional Chaining 进入 ES2020,不用满屏`x x.yyy`了
- 将您的SQL Server工作负载迁移到PostgreSQL –第1部分
- ASP.NET MVC 中解决Session,Cookie等依赖的方式
- 计算机使用的安全问题,大学计算机基础 教案 了解计算机使用中的安全问题(范文).doc...
- 什么浏览器好用_为什么国外的UC浏览器这么好用
- android中设置控件的搞,Android中如何自定义控件
- 疯狂的html css,疯狂Html+CSS+JS 中JS总结
- php mysql 非空_PHP-为什么mysql接受非空字段为null