java 反射读取枚举值上的注解信息

JAVASE 的API并没有提供获取枚举值注解信息的方法,只能获取到enum类上的注解,但是有一种场景:通过注解为枚举值增加额外的功能。

enum作为数据字典,当为enum的各个枚举值增加一个新的属性值时,有两种方式:

  1. 增加一个属性值,通过多种参数的构造方法,来实现;
  2. 增加一个注解,并且放置在枚举值上;
    本文来实现第二种方式,遇见的难题: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());
    }
}

运行结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值