这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。
对于对象、成员变量、方法相关的反射实现,大家应该比较熟悉了。今天,我们聊聊与枚举相关的反射内容。
枚举简介
枚举enum为java 5版本新增的一种特性。其使用起来非常简单:
- 定义枚举
public enum PayStatus {
WAITING_PAY(1, "待支付"),
FINISH_PAY(2, "支付完成"),
RETURN(3, "已退回"),
;
private Integer code;
private String msg;
PayStatus(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
- 直接使用
PayStatus.WAITING_PAY
即可表示一种状态
public class Order {
private PayStatus payStatus;
public static void main(String[] args) {
Order order = new Order();
order.setPayStatus(PayStatus.FINISH_PAY);
}
public PayStatus getPayStatus() {
return payStatus;
}
public void setPayStatus(PayStatus payStatus) {
this.payStatus = payStatus;
}
}
java.lang.Enum 类
在Java世界中,万物皆是对象。那枚举又是什么类「对象」呢?当然它肯定是Object类对象。除此之外,它还是java.lang.Enum类的对象。
官方文档的描述
* This is the common base class of all Java language enumeration types.
*
* More information about enums, including descriptions of the
* implicitly declared methods synthesized by the compiler, can be
* found in section 8.9 of
* <cite>The Java™ Language Specification</cite>.
* @since 1.5
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
...
}
// 中文大意:
这是所有 Java 语言枚举类型的公共基类。 有关枚举的更多信息,包括对编译器合成的隐式声明方法的描述,可以在Java™ 语言规范的第 8.9 节中找到
示例代码
public static void main(String[] args) {
System.out.println(PayStatus.class.getSuperclass());
System.out.println(PayStatus.FINISH_PAY.getClass().getSuperclass());
}
// 控制台输出:
class java.lang.Enum
class java.lang.Enum
从文档描述和示例代码可以看出,所有的枚举类都是继承java.lang.Enum类,只是这个继承不需要我们在代码显式定义出来。这就好比所有类默认继承Object,而不需要我们手动书写继承Object类。
Enum
类也很简单,它只有两个属性:
-
name 枚举的名称
-
ordinal 枚举的顺序
这两个属性都被final修饰,这两个值在定义枚举的时候就确定了,如WAITING_PAY(1, "待支付")
就已经确定其name为「WAITING_PAY」,ordinal为0。
其中name在toString方法有用到。
public String toString() {
return name;
}
所以我们平时在控制台看到枚举值(toString)就是我们定义枚举的名称.
枚举相关的反射
与枚举相关的反射方法只有一个:Class
类中getEnumConstants()
方法,可以获取枚举类下的所有枚举值。
用法示例:
public class EnumUtil {
static Map<String, Class> enumMap= new HashMap<>();
static {
enumMap.put("payStatus", PayStatus.class);
enumMap.put("payType", PayType.class);
}
public static List<String> getEnumsByType(String type) {
List<String> list = new ArrayList<>();
Class enumClass = enumMap.get(type);
// 获取所有枚举值
Object[] enumConstants = enumClass.getEnumConstants();
for (Object obj : enumConstants) {
list.add(String.valueOf(obj));
}
return list;
}
public static void main(String[] args) {
List<String> payStatus = getEnumsByType("payStatus");
System.out.println(payStatus);
}
}
// 控制台输出结果:
[WAITING_PAY, FINISH_PAY, RETURN]
因为枚举本身就很简单,所以通过反射动态获取枚举值的场景很少。前后端交互场景,可以通过枚举的反射机制实现数值与枚举的对应。