文章目录
一、介绍
1、概念
枚举是一种数据类型,用于定义一组命名的常量。枚举常量通常表示一组相关的值,例如颜色、方向、状态等。通过使用枚举,我们可以将一组相关的常量组织在一起,使代码更加清晰和可读。在许多编程语言中,枚举常量可以通过名称来引用,而不是使用具体的数值。这使得代码更易于理解和维护。
2、使用场景
在Java中,类的对象是有限个,确定的,也就是有限个固定值,这个类我们就可以定义为枚举类,如下:
性别:男女
月份:1,2…12
星期:一、二…日
3、好处
- 提高代码的可读性的可维护性,比如一个int类型,直接设置为1,根据就不知道什么意思,一头雾水,使用枚举,命名好,不用看注释就能知道什么意思
- 解耦,好扩展,常量值变动,直接改对应枚举值就行
4、特点
- 任意两个枚举成员不能具有相同的名称
- 多个枚举成员之间使用逗号分隔,最后一个成员用分号
- 枚举类型成员都可以看作是 Enum 类的实例,被public static final修饰
- 构造器默认使⽤private修饰
- 一般禁止写set方法,因为基本是只读的,写上也不会报错
二、如何自定义枚举
1、 JDK1.5之前的写法
通过类常量来实现,代码如下:
public class ProgrammingLanguage {
private final Integer id;
private final String desc;
private ProgrammingLanguage(Integer id, String desc) {
this.id = id;
this.desc = desc;
}
public static final ProgrammingLanguage JAVA = new ProgrammingLanguage(1, "java");
public static final ProgrammingLanguage PYTHON = new ProgrammingLanguage(2, "python");
public static final ProgrammingLanguage GOLANG = new ProgrammingLanguage(3, "go");
public static final ProgrammingLanguage C = new ProgrammingLanguage(4, "c");
public static final ProgrammingLanguage PHP = new ProgrammingLanguage(5, "php");
public Integer getId() {
return id;
}
public String getDesc() {
return desc;
}
}
2、 JDK1.5开始的写法
通过 enum 关键字声明枚举,代码如下:
public enum ProgrammingLanguageEnum {
JAVA(1, "java"),
PYTHON(2, "python"),
GOLANG(3, "go"),
C(4, "c"),
PHP(5, "php");
private Integer id;
private String desc;
ProgrammingLanguageEnum(Integer id, String desc) {
this.id = id;
this.desc = desc;
}
public Integer getId() {
return id;
}
public String getDesc() {
return desc;
}
}
可以简写,没有显式地声明属性的话,构造器,方法都可以省略不写
public enum SexEnum {
MAN,
WOMAN;
}
3、 两种方式区别
- 使用 enum 关键字声明枚举类的上层父类 :java.lang.Enum
- 使用类常量实现枚举类的上层父类:java.lang.Object
三、常用方法
- name():返回枚举常量的名称
- ordinal():返回枚举常量的序号(它在枚举声明中的位置,其中初始常量被分配为零序数)
- toString():返回枚举常量的名称
- values():返回枚举类对象的数组
- valueOf():通过对象名字获取这个枚举对象,对象的名字必须传正确,区分大小写,否则抛出异常
1、返回常量信息
ProgrammingLanguageEnum programmingLanguage = ProgrammingLanguageEnum.JAVA;
System.out.println(programmingLanguage.name()); // JAVA
System.out.println(programmingLanguage.ordinal()); // 0
System.out.println(programmingLanguage); // JAVA
2、返回枚举对象的数组
ProgrammingLanguageEnum[] values = ProgrammingLanguageEnum.values();
for (ProgrammingLanguageEnum value : values) {
System.out.println(value);
}
输出结果如下:
JAVA
PYTHON
GOLANG
C
PHP
3、通过对象名字获取这个枚举对象
对象的名字必须传正确,区分大小写,否则抛出异常
ProgrammingLanguageEnum programmingLanguage = ProgrammingLanguageEnum.valueOf("JAVA");
System.out.println(programmingLanguage); // JAVA
4、关于name和toString的疑惑,两者好像都是返回一样的?那应该使用哪个?
两者都是用于获取枚举常量的字符串表示,大多数程序员应该优先使用 toString 方法,因为 toString 方法可能会返回更用户友好的名称,此方法主要用于正确性取决于获取确切名称的特殊情况,该名称不会因版本而异。
四、应用场景
1、实现接口,调用不同方法
定义一个接口,统一枚举方法,枚举类实现该接口,通过实现不同对象调用不同方法
public enum ProgrammingLanguage implements Forlan{
JAVA(1, "java"){
@Override
public void print() {
System.out.println("Forlan,这是java");
}
},
PYTHON(2, "python"){
@Override
public void print() {
System.out.println("Forlan,这是python");
}
},
GOLANG(3, "go"){
@Override
public void print() {
System.out.println("Forlan,这是go");
}
},
C(4, "c"){
@Override
public void print() {
System.out.println("Forlan,这是c");
}
},
PHP(5, "php"){
@Override
public void print() {
System.out.println("Forlan,这是php");
}
};
...
2、通过属性值找到对应的属性值
使用增强get方法,遍历枚举找到对应的属性值
public static Integer getId(String desc) {
for (ProgrammingLanguageEnum vlaue : values()) {
if (vlaue.desc.equals(desc)) {
return vlaue.getId();
}
}
return null;
}
public static String getDesc(Integer id) {
for (ProgrammingLanguageEnum value : values()) {
if (value.getId().equals(id)) {
return value.getDesc();
}
}
return "未知";
}
3、实现设计模式
3.1 单例
在单例中,可以使用枚举值,作为参数,例如:
ProgrammingLanguage programmingLanguage = ProgrammingLanguage.JAVA;
3.2 责任链
public enum FilterTypeEnum {
BEFORE {
@Override
public FilterTypeEnum doFilter() {
System.out.println("执行前过滤");
return AROUND;
}
},
AROUND {
@Override
public FilterTypeEnum doFilter() {
System.out.println("执行中过滤");
return AFTER;
}
},
AFTER {
@Override
public FilterTypeEnum doFilter() {
System.out.println("执行后过滤");
return null;
}
};
public abstract FilterTypeEnum doFilter();
public static void main(String[] args) {
FilterTypeEnum filterTypeEnum = FilterTypeEnum.BEFORE;
while (filterTypeEnum != null) {
filterTypeEnum = filterTypeEnum.doFilter();
}
}
}