JAVASE 的API并没有提供获取枚举值注解信息的方法,只能获取到enum类上的注解,但是有一种场景:通过注解为枚举值增加额外的功能。
enum作为数据字典,当为enum的各个枚举值增加一个新的属性值时,有两种方式:
本文来实现第二种方式,遇见的难题:JAVASE 的API并没有提供获取枚举值注解信息的方法,只能获取到enum类上的注解。
解决办法: 通过获取枚举值Field对象 ,来实现:
代码实现
两个注解:需要去增强枚举值的功能
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Log {
//是否开启
boolean open() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Cost {
double min();
double max();
public enum StudyEnum {
@Log(open = true)
@Cost(min = 10.0, max = 99.0)
JAVA("java", "java基础"),
@Cost(min = 20.0, max = 79.0)
PHP("php", "php基础");
private String actualName;
private String desc;
public String getActualName() {
return actualName;
public void setActualName(String actualName) {
this.actualName = actualName;
public String getDesc() {
return desc;
public void setDesc(String desc) {
this.desc = desc;
private static final Map<String, Cost> costCache = new HashMap<>();
private static final Map<String, Log> logCache = new HashMap<>();
private static final Map<String, StudyEnum> cache = new HashMap<>();
StudyEnum(String actualName, String desc) {
this.actualName = actualName;
this.desc = desc;
//对象初始化时,执行下面的方法,将注解上的枚举值解析到cache中
static {
//将枚举属性值的name和Field映射为Map
Map<String, Field> fieldCache = Arrays.stream(StudyEnum.class.getDeclaredFields()).
filter(Field::isEnumConstant).
collect(Collectors.toMap(Field::getName, Function.identity()));
//遍历所有的枚举值
for (StudyEnum studyEnum : StudyEnum.class.getEnumConstants()) {
String keyName = studyEnum.name();
//原始的cache
cache.put(keyName, studyEnum);
Field field = fieldCache.get(keyName);
//不包含原始,则停止解析
if (!field.isAnnotationPresent(Log.class) || !field.isAnnotationPresent(Cost.class)) {
continue;
//获取日志注解
parsingLogAnno(keyName, field);
//获取价格注解
parsingCostAnno(keyName, field);
* 获取注解的属性
public static StudyEnumInfo resolve
(String name) {
StudyEnum studyEnum = cache.get(name);
if (studyEnum == null) {
return null;
Log log = logCache.get(name);
Cost cost = costCache.get(name);
StudyEnumInfo studyEnumInfo = new StudyEnumInfo();
studyEnumInfo.setName(studyEnumInfo.name);
studyEnumInfo.setDesc(studyEnum.desc);
studyEnumInfo.setLogAnno(log);
studyEnumInfo.setCostAnno(cost);
return studyEnumInfo;
* 获取注解的属性
public StudyEnumInfo resolve() {
return resolve(this.name());
//解析日志注解
private static void parsingLogAnno(String keyName, Field field) {
Log logAnno = field.getDeclaredAnnotation(Log.class);
if (logAnno != null) {
logCache.put(keyName, logAnno);
//解析花费注解
private static void parsingCostAnno(String keyName, Field field) {
Cost costAnno = field.getDeclaredAnnotation(Cost.class);
if (costAnno != null) {
costCache.put(keyName, costAnno);
@Data
public static class StudyEnumInfo {
private String name;
private String desc;
private Log logAnno;
private Cost costAnno;
public class Test {
//完成对象的解析
public static void main(String[] args) {
//info对象
StudyEnum.StudyEnumInfo info = StudyEnum.JAVA.resolve();
System.out.println(info.getCostAnno().max());
System.out.println(info.getLogAnno().open());
