自定义枚举以及如何在反射中获取枚举值

时间:2021-08-08 10:40:39

枚举也是类,在定义枚举的时候,其实是定义了一个枚举集合,然后在这个集合中包含一些列枚举值。比如性别可以是一个枚举集合,可能中包含男性、女性等枚举值。

定义枚举集合

以性别这个枚举集合为例,先来定义两个枚举值,分别为MALE和FEMALE:

publicenum Gender {
MALE, FEMALE
}

JAVA编译器会把这MALE和FEMALE转成两个枚举值。

枚举类-Enum(name, ordinal)

Emum在Java中为抽象类,它的默认构造函数接受两个参数:枚举的字符串表示、集合序数。比如MALE,实际上它是Enum('MALE', 0);FEMALE,实际是Enum('FEAMLE', 1)。

Name与ordinal

枚举类有两个固定的属性,即name和ordinal。这两个属性都是只读的,其中name的值就是枚举值的名字,而且大小写完全一致,比如MALE.name()返回永远都是"MALE"。

属性ordinal是整数,表示枚举值在枚举集合中的序数,其实就是枚举值的出现顺序,这个属性值也是只读的,而且由ordinal()获取。

但是,如果我们在自定义的枚举类中声明与name或ordinal同名的属性,并不影响name()和ordinal()方法的返回值。

自定义枚举类的构造函数

正如前面讲述的,Enum有默认的构造函数,并且接受两个参数。其实Java中的Enum也是类,所以,我们可以像类一样修改枚举类的构造函数,甚至添加新的方法和属性。

publicenum Gender {       MALE("male", 1), FEMALE("female", 0);       private final String name;       private final int id;       Gender(Stringname, int ordinal){        this.name = name;        this.id =ordinal;    }     public StringgetName() {        return name;    }     publicint getId() {        return id;    }}

但正如我们所见,以上重新定义了name,但是MALE.name()返回的仍然是"MALE",而MALE.getName()返回的是"male"。

获取枚举集合的所有枚举值

运行时,枚举类会多几个方法,比如Enum.values(),这个方法会放回该枚举内所有的枚举常量,顺序按ordinal的顺序排列。但如果在写代码的时候你不知道它将来是何种枚举类,也可以使用type.getEnumConstants()获取运行时枚举类的所有枚举值(下面的反射中就会用到)。

实现接口的枚举在反射中的应用

枚举也是类,所以它也可以实现接口。这种实现方式在做反射时,特别有用。比如POJO的属性是自定义枚举类,当我们不能根据name()来判断字符串对应的是哪个枚举值时,就可以通过一个公共的方法来判断给出的字符值对应的是哪个枚举值。

publicinterfaceCustomEnum {    public String value();} publicenum Gender implements CustomEnum{    MALE("man"), FEMALE("woman");       privatefinal String name;       Gender(String name) {        this.name = name;    }     public StringgetName() {        return name;    }     @Override    public Stringvalue() {        // TODOAuto-generated method stub        return this.name;    }  }

在做反射的时候,我们就可以用value()方法来判断字符值对应的枚举值:

if (type.isEnum()){    if (CustomEnum.class.isAssignableFrom(type)) {        return resolveExcelEnum(text,(Class<CustomEnum>)type);    } else {        return resolveEnumValue(text, type);}

自定义枚举类型的判断方式:

private CustomEnumresolveCustomEnum(String value, Class<CustomEnum>type) {    for (CustomEnum constant : type.getEnumConstants()){        if (constant.value().equalsIgnoreCase(value)) {            returnconstant;        }    }       return null;} 

一般枚举类型根据name()来判断枚举值

private <T> TresolveEnumValue(String value, Class<T> type) {    for (T constant : type.getEnumConstants()){        if (constant.toString().equalsIgnoreCase(value)) {            return constant;        }    }       return null;}