一、枚举
在数学和计算机科学理论中,一个数据集的 枚举 是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。枚举,就是一个可列举的有限对象的集合。
JDK1.5之前,需要自定义枚举类;
JDK1.5之后,可以使用 Enum 关键字定义枚举类,写法超级简单;
JDK1.6之后,switch 语句支持枚举,使代码更简洁更健壮;
若枚举类只有一个成员,则可以作为一种单例模式的实现方式,也就是说,单例模式可以看做枚举的一个特例;
1. 应用场景
可以应用到所有可以定义出有限个值的场景,常常用于设定为常量,比如:
- 一年有四季,定义四季的名称;
- 一年有12个月,定义月份的名称;
- 所有颜色都是有3个原色组成的,可以定义3个原色;
2. 典型应用
线程的状态是使用枚举类实现的, java.lang.Thread.State ,可以看到其定义了线程的各个状态。
@Test
public void testTheadState(){
//获取枚举对象,并循环输出
Thread.State[] states = Thread.State.values();
for(Thread.State s : states){
System.out.println(s);
}
}
运行结果:
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED
二、代码实现
1. 自定义枚举类
/**
* 自定义实现的枚举类——季节
* 枚举是可列举的有限个对象的集合,一年只有四季,都可以列举出来,故适合采用枚举形式
* 自定义枚举类的写法和单例模式类似,或者可以说,单例模式就是枚举类只有一个对象的特例。
*
* 自定义枚举类有以下关键点:
* 1. 枚举类的构造方法必须私有化,不允许外部调用,防止通过外部改变枚举对象;
* 2. 枚举类的属性必须定义为private final,避免外部修改;
* 3. 枚举类需要自己创建枚举对象,枚举对象必须定义为public static final,提供外部访问方式。
*
* @author hello
* @date 2020/11/06
*/
public class CustomSeasonEnum {
/**
* 属性定义为private final,避免被外部修改
*/
private final String seasonName;
private final String seasonDesc;
/**
* 构造方法私有化,可指定构造方法的参数,方便实例化时赋值
*/
private CustomSeasonEnum(String seasonName, String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
/**
* 定义枚举对象,最关键的地方
*/
public static final CustomSeasonEnum SPRING =
new CustomSeasonEnum("Spring","春风拂面");
public static final CustomSeasonEnum SUMMER =
new CustomSeasonEnum("Summer","生如夏花");
public static final CustomSeasonEnum AUTUMN =
new CustomSeasonEnum("Autumn","秋风瑟瑟");
public static final CustomSeasonEnum Winter =
new CustomSeasonEnum("Winter","冬日暖阳");
}
编写测试用例如下:
public class CustomSeasonEnumTest {
@Test
public void testCustomEnum(){
CustomSeasonEnum season = CustomSeasonEnum.SPRING;
System.out.println(season.getSeasonName() + " : " + season.getSeasonDesc());
}
}
运行结果:可以看到,调用正确
Spring : 春风拂面
2. 使用enum关键字定义枚举类
2.1 使用enum定义的枚举类
使用enum定义的枚举类,只是一种简化了形式的自定义枚举类,其也可以包含自定义属性、方法、构造方法等,相比自定义枚举类,简化了枚举对象的声明,省略了public static final及new 对象等语句,枚举对象的定义是线程安全的,故也可以使用枚举方式定义单例模式。
与自定义枚举类相比,使用enum枚举类有以下特点:
- 枚举对象必须放到最前面,也就是必须在其他自定义属性或方法的签名;
- 忽略了public static final 及 new 对象等语句;
/**
* 使用enum关键字定义的枚举值
*/
public enum SeasonEnum {
/**
* 一年四季,依次为:春天、夏天、秋天、冬天
* 相比自定义枚举方式:
* 1. 必须放到最前面,也就是必须在其他自定义属性或方法的签名;
* 2. 忽略了public static final 及 new 对象等语句;
*/
SPRING("Spring","春风拂面"),
SUMMER("Summer","生如夏花"),
AUTUMN("Autumn","秋高气爽"),
WINTER("Winter","冬日暖阳");
/**
* 枚举类的属性
*/
private final String seasonName;
private final String seasonDesc;
/**
* 构造方法私有化
*/
private SeasonEnum(String seasonName, String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
/**
* 获取属性的公共方法
*/
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
}
2.2 最简单的枚举类示例
最简单的枚举形式是只有枚举对象,没有任何属性,也不声明构造方法,也没有定义方法。
//最简单的枚举示例
public enum ColorEnum {
RED,GREEN, BLUE ;
}
//测试用例
@Test
public void testColorEnum(){
//获取红色
ColorEnum red = ColorEnum.RED;
System.out.println(red);
System.out.println("------");
//获取所有对象
ColorEnum[] colors = ColorEnum.values();
for (ColorEnum colorEnum : colors){
System.out.println(colorEnum);
}
}
运行结果:
RED
------
RED
GREEN
BLUE
2.3 常用方法
2.3.1 values()
方法作用:获取所有的枚举对象数组,可以依次遍历,并做相应判断;
方法示例:
@Test
public void testValues(){
ColorEnum[] colorEnums = ColorEnum.values();
for(ColorEnum colorEnum : colorEnums){
System.out.println(colorEnum);
}
}
//运行结果:
RED
GREEN
BLUE
2.3.2 valueOf(String name)
方法作用:根据字符串获取相同名称的枚举对象;
注意事项:
- 要求传入的字符串名称必须是枚举对象的名称,不能随意输入;
- 若字符串输入错误,并不是返回null,而是程序报错;
方法示例:
(1)正确示例:获取对应名称的枚举对象
@Test
public void testValueOf(){
String colorName = "RED";
ColorEnum colorEnum = ColorEnum.valueOf(colorName);
System.out.println(colorEnum);
}
//运行结果:
RED
(2)错误示例:抛出异常IllegalArgumentException
@Test
public void testValueOfError(){
String colorName = "REEEEED";
ColorEnum colorEnum = ColorEnum.valueOf(colorName);
System.out.println(colorEnum);
}
//运行结果:抛出异常IllegalArgumentException
java.lang.IllegalArgumentException: No enum constant com.tengol.demo. javase .basic.enums.ColorEnum.REEEEED
at java.lang.Enum.valueOf(Enum.java:238)
at com.tengol.demo.javase.basic.enums.ColorEnum.valueOf(ColorEnum.java:3)
2.4 枚举类实现接口
使用enum关键字定义的枚举类都继承自抽象类 java.lang.Enum ,因为Java不支持多继承,所以枚举类无法再继承其它类,但可以实现一个或者多个接口。
枚举类可以实现接口,同时枚举对象也可以重写所实现接口的抽象方法,通过反编译方式可以看到,枚举对象重写接口方法时通过匿名内部类方式实现。
第一步:定义接口
/**
* 接口:打印信息
*/
public interface Info {
public void print();
}
第二步:枚举类实现接口方法,枚举对象可以重写方法
public enum WeekEnum implements Info {
/**
* 一周七天
*/
MONDAY{
@Override
public void print() {
super.print();
}
},
TUESDAY {
@Override
public void print() {
System.out.println("Tuesday...");
}
},
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
public void print() {
System.out.println("WeekEnum...");
}
}
测试用例:
@Test
public void testImpl(){
//周二重写了print()方法,执行重写的方法
WeekEnum tue = WeekEnum.TUESDAY;
tue.print();
//周三未重写,执行WeekEnum的print()方法
WeekEnum wed = WeekEnum.WEDNESDAY;
wed.print();
}
运行结果:
Tuesday...
WeekEnum...
部分笔记内容来自尚硅谷的培训视频,如有兴趣,请关注。
笔记虽小,但是希望对你有用,感谢你的支持,你的阅读是对我的最大支持。
关键词:java , 枚举 , enum , 枚举类