枚举类型
枚举类型定义了一个枚举值的列表。每个值都是一个标识符。例如
1 | enum MyFavoriteColor{RED,BLUE,GREEN,YELLOW} |
枚举值类似于一个常量,因此,按惯例拼写都是使用大写字母(RED,BLUE...)。按惯例,枚举类型命名类似于一个类,每个单词的第一个字母大写。
一旦定义了类型,就可以声明这个类型的变量了
MyFavoriteColor color;
枚举的作用和目的:枚举就是要让某个类型的变量的取值只能是若干个固定值中的一个或者null,但不能有其它值,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值。普通变量的方式在开发阶段无法实现这一目标(类型安全的)
注意:必须使用枚举类型名称作为限定词来引用一个值,比如BLUE。
定义一个普通的类来模拟实现枚举的功能:
- 私有的构造方法。
- 每个元素分别用一个公用的静态成员变量表示,每一个枚举元素都是一个自身实例对象。
- 可以有若干共有方法或抽象方法,例如,要提供nextDay方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class WeekDay{ private WeekDay(){} public static final WeekDay SUN = new WeekDay(); public static final WeekDay MON = new WeekDay(); public static final WeekDay TUE = new WeekDay(); public static final WeekDay WED = new WeekDay(); public static final WeekDay THU = new WeekDay(); public static final WeekDay FRI = new WeekDay(); public static final WeekDay SAT = new WeekDay(); //计算下一天 public WeekDay nextDay(){ if ( this == SUN) return MON; else if ( this == MON) return TUE; else if ( this == TUE) return WED; else if ( this == WED) return THU; else if ( this == THU) return FRI; else if ( this == FRI) return SAT; else return SUN; } } |
到此,我们看到此类中有大量的if…else语句,感到太麻烦和繁琐,于是我们把每一个元素的nextDay都用一个独立的方法来做,于是稍作修改后的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public abstract class WeekDay{ private WeekDay(){} //此处表示只是一个内部类,是WeekDay的子类,这个子类没有名称,称为匿名内部类。 // new WeekDay(){……};表示这是一个内部类,没有名称,这个内部类是WeekDay的子类 public static final WeekDay SUN = new WeekDay(){ public WeekDay nextDay(){ return MON;} }; public static final WeekDay MON = new WeekDay(){ public WeekDay nextDay(){ return TUE;} }; public static final WeekDay TUE = new WeekDay(){ public WeekDay nextDay(){ return WED;} }; public static final WeekDay WED = new WeekDay(){ public WeekDay nextDay(){ return THU;} }; public static final WeekDay THU = new WeekDay(){ public WeekDay nextDay(){ return FRI;} }; public static final WeekDay FRI = new WeekDay(){ public WeekDay nextDay(){ return SAT;} }; public static final WeekDay SAT = new WeekDay(){ public WeekDay nextDay(){ return SUN;} }; //要让每个元素自己写自己的方法,我们把它定义为抽象的方法,所以,类也变成抽象的,于是我们不能用它自己来创建实例对 象,而只能用它的子类来创建实例对象。 public abstract WeekDay nextDay(); } |
枚举可以很方便的帮我们完成该功能检查。定义一个枚举:
1 2 3 | public enum Day{ SUN,MON,TUE,WED,THU,FRI,SAT; } |
如同其它类型一样,可以在一行语句中声明和初始化一个变量:
Day weekDay = Day.SAT;
枚举类型被作为一个特殊的类来对待。因此,枚举类型的变量是引用变量。一个枚举类型是Object类和Comparable接口的子类。因此,枚举类型继承了Object类中的所有方法,以及Comparable接口的compareTo方法。例外,可以在一个枚举类型的对象上面使用下面的方法:
- public String name():为对象返回名字值
- public int ordinal():返回和枚举值关联的序号值。枚举类型中的第一个值具有序号数0,第二个值具有序号值1,第三个为2,以此类推。
枚举类型的静态方法:
valueOf(str:String):将枚举字面值str转换为枚举类型
枚举的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package edu.uestc.avatar; public class EnumerateTypeDemo{ /* * 枚举类型可以定义在一个类中(内部类);或者单独定义(独立的类) * 当一个枚举类型在一个类中声明时,类型必须为类的一个成员,而不能在方法中声明。而且,类型总是static的 * 所以,该处的static可以省略;可以用于内部类的可见性修饰符也可以应用到在一个类中定义的枚举类型中 */ static enum Day{SUN,MON,TUE,WED,THU,FRI,SAT;} public static void main(String[] args) { Day day1 = Day.FRI; Day day2 = Day.THU; System.out.println( "day1's name is " + day1.name()); System.out.println( "day2's name is " + day2.name()); System.out.println( "day1's ordinal is " + day1.ordinal()); System.out.println( "day2's ordinal is " + day2.ordinal()); System.out.println(day1.equals(day2)); System.out.println(day1.toString()); System.out.println(day1.compareTo(day2)); } } |
通过枚举变量使用if或者switch语句
枚举变量具有一个值。程序经常需要根据取值来执行特定的动作。例如,如果值为Day.SAT,则全程所有商品打8折;如果值为Day.FRI,则打9折,等等。可以使用if语句或者switch一句来测试变量的值。
使用foreach循环处理枚举值
每个枚举类型都有一个静态方法values(),可以返回这个类型中所有的枚举值到一个数组中。例如
Day[] days = Day.values();
可以使用通常的循环或者foreach来处理数组中所有的值
for(int i = 0; i < day.length; i++) sout:days[1] ===== for(Day day : days)sout:day;
具有数据域,构造方法和方法的枚举类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | //通过一个交通信号灯的例子来说明: public enum TrafficLamp{ RED( 30 ){ public TrafficLamp nextLamp(){ return GREEN;} }, YELLOW( 5 ){ public TrafficLamp nextLamp(){ return RED;} }, GREEN( 50 ){ public TrafficLamp nextLamp(){ return YELLOW;} }; //抽象方法,要求每个实例都需要对该方法做出实现,因为每个实例是其子类 public abstract TrafficLamp nextLamp(); //数据域,交通灯时间 private int time; //构造方法,枚举的构造方法必须为private的 private TrafficLamp( int time){ this .time = time; } //普通成员方法 public String description(){ return "" ; } public int getTime(){ return time; } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!