夯实Java基础(十六)——枚举类的使用
1、枚举类简介
枚举是仅容许特定数据类型值的有限集合。例如我们平时生活中星期一到星期日这七天就是一个特定的有限集合,一年四季的春夏秋冬也同样是的,它们都是枚举。枚举和我们数学中的集合非常相似,如果我们定义一个Season={Spring、Summer、Autumn、Winner}这样的集合,当我们要从集合中取出数据时,只能从集合中有的值来取,否则就会找不到。
枚举类也就顾名思义,枚举类:类的对象是有限和固定的集合。枚举类是JDK1.5中才出现的新特性,在Java中用enum关键字来修饰,enum的全称是enumeration。所有被enum修饰的类都会默认的继承自java.lang.Enum这个类,而不是Object类。
有的人并不推荐使用枚举。而有的人推荐使用,认为枚举使用方便。这里就要说上一句仁者见仁智者见智吧。总之,知识装进自己的脑袋总不会丢,所以我们先学会它再说。
2、枚举类的定义
我们知道枚举类是JDK1.5才有的特性,那么在之前是怎么来定义的呢?我们来回顾一下:
public class EnumTest {
public static final String SPRING="SPRING";
public static final String SUMMER="SUMMER";
public static final String AUTUMN="AUTUMN";
public static final String WINTER="WINTER"; public static void main(String[] args) {
System.out.println(EnumTest.SPRING);
System.out.println(EnumTest.SUMMER);
show(EnumTest.SPRING);
show("enum...");
} public static void show(String season){
System.out.println(season);
}
}
在没有枚举类之前我们使用public static final修饰的全局常量来表示枚举,虽然这样可以达到效果,但是也会存在缺陷。
①、类型不安全。若一个方法中要求传入season这个参数,使用常量的话,形参就是String类型,而开发者可以传入任何String类型的值,但是如果是枚举类型的话,就只能传入枚举类中包含的对象。
②、代码复杂。如果我们定义时是这样定义常量的 public static final int SPRING=1。而我们要的结果是输出SPRING这个字符串,那么我们还要在方法中进行大量if else 判断,如下所示。
if (season==1){
System.out.println("SPRING");
}
......
而使用枚举类就不会存在以上问题,话不多说,直接上代码示例:
public enum Season {
SPRING, SUMMER, AUTUMN, WINNER
}
对,没错,代码量就是这么的少。我们使用枚举类会让代码更加直观,类型更安全,代码量更少。但是要注意:在枚举类中声明枚举变量时,最前面不能含有任何变量,方法,构造器等内容,也就是说枚举变量必须声明在第一行。多个对象之间需要用逗号隔开,如果枚举变量没有参数(如SPRING(1),后面会讲),分号可以省略。
再来看看枚举类的简单使用:
public static void main(String[] args) {
Season spring = Season.SPRING;
System.out.println(spring);
show(spring);
} public static void show(Season season){
System.out.println(season);
}
像上述代码那样,我们可以直接使用枚举类名称 . 对象名称来引用枚举的值,这便是枚举类型的最简单的使用。
3、在switch语句中的使用
在之前的switch语法中只支持int和char类型的数据,但是随着枚举类型的出现,enum类型也可以在switch中使用了,我们看一下怎么在switch语句中使用:
public enum Season {
SPRING, SUMMER, AUTUMN, WINNER;
} class Test{
public static void main(String[] args) { Season season = Season.SPRING;
switch (season){
case SPRING:
System.out.println(Season.SPRING);
break;
case SUMMER:
System.out.println(Season.SUMMER);
break;
case AUTUMN:
System.out.println(Season.AUTUMN);
break;
case WINNER:
System.out.println(Season.WINNER);
break;
}
}
}
枚举在switch中使用比较简单,只需了解有这么个情况就OK了。
4、枚举类中常用方法
即然所有的枚举类都是继承自java.lang.Enum这个类,那么每个枚举类都必定有可用的方法。我们只例举比较常用方法:
- Season.valueOf(String name) 方法:返回具有指定名称的指定枚举类型的枚举常量(区分大小写),如果没有则报错。
- Season.values()方法:返回枚举类中包括所有枚举对象的数组。该方法可以很方便地遍历枚举值。
- 枚举类变量.name()方法:返回当前枚举类对象的名称。它和toString()方法是一模一样的。
- 枚举类变量.ordinal()方法:返回此枚举常数的序数(其枚举声明中的位置,其中初始常数的序数为零)。
- 枚举类变量.toString()方法:返回当前枚举类对象的名称。
常用方法的举例:
public enum Season {
SPRING, SUMMER, AUTUMN, WINNER;
} class Test{
public static void main(String[] args) {
//Season.valueOf()
Season season1 = Season.valueOf("SPRING");
System.out.println(season1);
System.out.println("-------------");
//Season.values()
Season[] values = Season.values();
for (Season season2:values){
System.out.println(season2);
}
System.out.println("-------------");
Season summer = Season.SUMMER;
//name()
System.out.println(summer.name());
//ordinal()
System.out.println(summer.ordinal());
//toString()
System.out.println(summer.toString());
}
}
还有一些其他的方法就不介绍了,有些应该都知道,而有些则不常用。有感兴趣的话可以自己去看看官方API或者源码,都比较的简单。
5、给枚举变量添加自定构造器
在前面的分析中,我们都是基于简单枚举类型来定义的,并没有在枚举类中定义变量、方法、构造器等结构。实际上枚举类和普通类有着相同的特征,除了不能使用继承之外(因为编译器会自动为我们继承Enum抽象类,而Java只支持单继承),我们完全可以把枚举类当成普通类,下面我们来感受一下吧。
public enum Season {
SPRING("春暖花开"),
SUMMER("夏日炎炎"),
AUTUMN("秋高气爽"),
WINNER("冬暖夏凉");//此时的分号不能省略 private String name; //系统默认构造器是private,而且必须是private的,用public则会报错
Season(String name) {
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
} class Test{
public static void main(String[] args) {
for (Season season:Season.values()){
System.out.println(season.name()+","+season.getName());
}
}
}
程序运行结果:
通过上述可知,虽然枚举类中可以普通类一样声明变量、成员方法、构造器。但是我们必须注意到以下几点:
①、枚举类变量必须放在第一行,如果枚举类变量有构造器,那么分号必须加上,否则可以省略。
②、枚举类的构造器必须是private的,系统会自动设置为private,我们也可以自己加上,但是不能用public等修饰符,否则会报错。
6、枚举类中定义抽象方法
枚举类即然和普通类一样,那么枚举类中就允许定义抽象类和接口,接口下一节讲。但是需要注意的是每个枚举变量都需要重写该方法,否则编译会报错。继续用上面的例子,只是在其中添加了一个抽象方法。
public enum Season {
SPRING("春暖花开"){
public String show(){
return "SPRING";
}
},
SUMMER("夏日炎炎"){
public String show(){
return "SUMMER";
}
},
AUTUMN("秋高气爽"){
public String show(){
return "AUTUMN";
}
},
WINNER("冬暖夏凉"){
public String show(){
return "WINNER";
}
};//此时的分号不能省略 private String name; //系统默认构造器是private,而且必须是private的,用public则会报错
Season(String name) {
this.name = name;
} //定义抽象方法
public abstract String show(); public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
} class Test{
public static void main(String[] args) {
for (Season season:Season.values()){
System.out.println(season.name()+","+season.getName()+",枚举变量方法返回值:"+season.show());
}
}
}
程序运行结果:
通过这种方式就可以轻而易举地定义每个枚举变量的不同行为方式。而且调用枚举变量中方法有两种方式,一种是枚举变量名称.方法,另一种是枚举类名.枚举变量.方法(如Season.SPRING.show());
7、枚举类实现接口
虽然枚举类不能再继承其他的类了,但是它还是能够实现接口的,举例:
interface Behaviour{
String show();
} public enum Season implements Behaviour{
SPRING("春暖花开"),
SUMMER("夏日炎炎"),
AUTUMN("秋高气爽"),
WINNER("冬暖夏凉");//此时的分号不能省略 private String name; //系统默认构造器是private,而且必须是private的,用public则会报错
Season(String name) {
this.name = name;
} @Override
public String show() {
return this.name;
}
} class Test{
public static void main(String[] args) {
for (Season season:Season.values()){
System.out.println(season.show());
}
}
}
这样使用起来还是比较的简单的。在枚举类中使用接口还有一个功能就是对一组数据进行分类,此时就可以利用接口来组织枚举。比如一年四季中包含的节气:
public interface Season {
enum Spring implements Season{
//立春,雨水,清明
SPRING_BEGINS,RAIN,TOMB_SWEEPING
}
enum Summer implements Season{
//夏至,芒种,小暑,大暑
SUMMER_BEGINS,GRAIN_INE_EAR,SLIGHT_HEAD,GREAT_HEAD
}
enum AUTUMN implements Season{
//立秋,寒露,霜降
AUTUMN_BEGINS,COLD_DEW,FROST
}
enum WINTER implements Season{
//立冬,小雪,大雪,冬至
WINTER_BEGINS,LIGHT_SNOW,HEAVY_SNOW,WINTER_SOLSTICE_FESTIVAL
}
} class Test{
public static void main(String[] args) {
//遍历Spring
Season.Spring[] values = Season.Spring.values();
for (Season season:values){
System.out.println(season);
}
}
}
//运行结果:
//SPRING_BEGINS
//RAIN
//TOMB_SWEEPING
通过上面这种方式我们可以很方便地组织枚举,同时还确保了具体类型属于春夏秋冬,而春夏秋冬则属于季节Season。
8、EnumSet,EnumMap的应用
EnumSet和EnumMap这两个都是关于枚举集合方面的知识,所以暂时不深入学习,仅用示例来简单了解一下。但是我们要清楚一点EnumSet是保证集合中的元素不重复。而EnumMap中的 key是enum类型,而value则可以是任意类型。
class Tests{
public static void main(String[] args) {
// EnumSet的使用
EnumSet<Season> set=EnumSet.allOf(Season.class);
System.out.println(set);
for (Season season:set){
System.out.println(season);
}// EnumMap的使用
EnumMap<Season,String> map=new EnumMap<Season, String>(Season.class);
map.put(Season.SPRING,"春暖花开");
map.put(Season.SUMMER,"夏日炎炎");
map.put(Season.AUTUMN,"秋高气爽");
map.put(Season.WINNER,"冬暖夏凉");
//遍历map有很多种方式,这里是map遍历的一种方式,这种方式是最快的
for (EnumMap.Entry<Season,String> entry:map.entrySet()){
System.out.println(entry.getKey()+","+entry.getValue());
}
}
}
程序运行结果:
夯实Java基础(十六)——枚举类的使用的更多相关文章
- 【Java基础】关于枚举类你可能不知道的事
目录 谈谈枚举 1. 枚举类的定义 2. 枚举类的底层实现 3. 枚举类的序列化实现 4. 用枚举实现单列 5. 枚举实例的创建过程是线程安全的 谈谈枚举 如果一个类的对象个数是有限的而且是不变的,我 ...
- java基础(十六)----- equals()与hashCode()方法详解 —— 面试必问
本文将详解 equals()与hashCode()方法 概述 java.lang.Object类中有两个非常重要的方法: public boolean equals(Object obj) publi ...
- 夯实Java基础(六)——包装类
1.包装类简介 我们都知道Java是面向对象编程语言,包含了8种基本数据类型,但是这8种基本数据类型并不支持面向对象的特征,它们既不是类,也不能调用方法.这在实际使用时存在很多的不便,比如int类型需 ...
- 夯实Java基础系列目录
自进入大学以来,学习的编程语言从最初的C语言.C++,到后来的Java,. NET.而在学习编程语言的同时也逐渐决定了以后自己要学习的是哪一门语言(Java).到现在为止,学习Java语言也有很长一段 ...
- 夯实Java基础系列14:深入理解Java枚举类
目录 初探枚举类 枚举类-语法 枚举类的具体使用 使用枚举类的注意事项 枚举类的实现原理 枚举类实战 实战一无参 实战二有一参 实战三有两参 枚举类总结 枚举 API 总结 参考文章 微信公众号 Ja ...
- Java实习生常规技术面试题每日十题Java基础(六)
目录 1.在Java语言,怎么理解goto. 2.请描述一下Java 5有哪些新特性? 3.Java 6新特性有哪些. 4.Java 7 新特性有哪些. 5.Java 8 新特性有哪些. 6.描述Ja ...
- 夯实Java基础系列9:深入理解Class类和Object类
目录 Java中Class类及用法 Class类原理 如何获得一个Class类对象 使用Class类的对象来生成目标类的实例 Object类 类构造器public Object(); register ...
- Bootstrap<基础十六> 导航元素
Bootstrap 提供的用于定义导航元素的一些选项.它们使用相同的标记和基类 .nav.Bootstrap 也提供了一个用于共享标记和状态的帮助器类.改变修饰的 class,可以在不同的样式间进行切 ...
- 夯实Java基础系列5:Java文件和Java包结构
目录 Java中的包概念 包的作用 package 的目录结构 设置 CLASSPATH 系统变量 常用jar包 java软件包的类型 dt.jar rt.jar *.java文件的奥秘 *.Java ...
- 夯实Java基础系列6:一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别!
目录 抽象类介绍 为什么要用抽象类 一个抽象类小故事 一个抽象类小游戏 接口介绍 接口与类相似点: 接口与类的区别: 接口特性 抽象类和接口的区别 接口的使用: 接口最佳实践:设计模式中的工厂模式 接 ...
随机推荐
- springboot学习4使用日志:logback
springboot学习4使用日志:logback 一.基本知识说明 SpringBoot默认使用logback作为日志框架 ,所以引入起步依赖后就可以直接使用logback,不需要其他依赖. Spr ...
- Strategic game POJ - 1463
题目链接 依旧是树形dp啦,一样的找根节点然后自下而上更新即可 设\(dp_{i,0}\)表示第i个不设,\(dp_{i,1}\)表示第i个设一个,容易得到其状态转移 \(dp_{i,0} = \su ...
- 排序算法之选择排序的python实现
选择排序算法的工作原理如下: 1. 首先在序列中找到最小或最大元素,存放到排序序列的前或后. 2. 然后,再从剩余元素中继续寻找最小或最大元素. 3. 然后放到已排序序列的末尾. 4. 以此类推,直到 ...
- 使用 vant 的 v-lazy 实现图片 vue 在移动端的懒加载
官方文档:https://youzan.github.io/vant/#/zh-CN/lazyload 引入 Lazyload 是 Vue 指令,使用前需要对指令进行注册 import Vue fro ...
- Shell编程WEB界面展示实践
操作系统:win7 虚拟机:Virtual box with Ubuntu13.10 WEB服务器: Nginx WEB服务器发布目录:/usr/local/nginx/html/c 测试文件:lis ...
- L298N模块的使用(文末有惊喜)
这个模块有两个供电口,标示着“12V输入”的是功率驱动电源输入,供电范围可以是7-46V, 一般12V供电就能满足我们大部分的DIY需求.标示着“5V输出可不接”的是逻辑供电, 当我们将“板载5V输出 ...
- 路由器安全-FPM
1.FPM(也叫NGACL) FPM是Cisco IOS新一代的ACL,叫做Flexible Packet Matching,灵活的包匹配. 根据任意条件,无状态的匹配数据包的头部,负载,或者全部. ...
- [WC2018]通道(乱搞,迭代)
[洛谷题面]https://www.luogu.org/problemnew/show/P4221 这个题以及[CTSC2018 暴力写挂]都有类似的乱搞做法能通过考场数据. 具体搞法就是随一个起点, ...
- 反射实现定位Servlet中的方法
public class BaseServlet extends HttpServlet{ @Override protected void service(HttpServletRequest re ...
- python基础之省份三级菜单
菜单 menu = { #定义一个字典 '北京':{ '海淀':{ '五道口':{ 'soho':{}, '网易':{}, 'google':{} }, '中关村':{ '爱奇艺':{}, '汽车之家 ...