通用的任意值转Java枚举常量工具类

Java 的枚举类型,自带一个valueOf() 方法,来转换字符串到对应的枚举常量,同时,也可以利用枚举类型的 values()[x] 按顺序去取相应的常量。但是对于有自定义数值的枚举,却需要自己处理。例如:

    public enum NamedColor {
        Red(0xFF0000,"红色"),
        Green(0x00FF00,"绿色"),
        Blue(0x0000FF,"蓝色");


        private int value;
        private String name;
        NamedColor(int value,String name){
            this.value=value;
            this.name = name;
        }

        public int getValue()
        {
            return this.value;
        }
        public String getName()
        {
            return  this.name;
        }

    }

若要把 0xFF0000,或者“红色”转成 NamedColor.Red, 可能需要专门针对这个枚举类写个方法了。

有没有通用的方法呢?本人受 MyBatis Plus的 EnumUtil工具类的启发,写了如下代码,利用Lamda表达式,可以将任意值和任意指定的枚举类型匹配。代码如下:

先声明一个IGetter的函数接口:

  @FunctionalInterface
    public interface IGetter<T> extends Serializable {
        Object apply(T source);
    }

然后如下处理:

public static  <E extends Enum> E valueOfEnum(@NotNull Class<E> enumClass, @NotNull Object value, @NotNull IGetter<E> ... vGetters )
    {
        // Step 1. 使用Java 自带的valueOf判断是否匹配枚举常量名
        try{
            E ec = (E) Enum.valueOf(enumClass,String.valueOf(value)) ;
            return ec;
        }catch (IllegalArgumentException e){
            log.debug(e.getMessage()+",Try to match with value and getters ...");
        }
        //Step 2 用指定的getter方法,逐个匹配枚举常量的属性值
        E[] enumConsts  = (E[])enumClass.getEnumConstants();
        // Step 2.1  确保以字符串类型给出的数字类型属性值value,也能匹配
        BigDecimal nv = null;
        try {
            nv = new BigDecimal(String.valueOf(value));
        }catch( Exception  ex ){
            log.debug(" Value:'{}' is NOT a valid number.{}",value,ex.getMessage() );
        }
        //Step 2.2
        for ( IGetter<E> getter:vGetters) {
            for (E e:enumConsts){
                Object ev = getter.apply(e);
                if (ev instanceof Number  && nv !=null && nv.compareTo(new BigDecimal(String.valueOf(ev))) == 0) {
                    return e;
                }
                if (Objects.equals(ev, value)) {
                    return e;
                }
            }
        }

        return null;
    }

调用方法:

NamedColor color1 = EnumUtils.valueOfEnum(NamedColor.class,"红色", NamedColor::getName);
NamedColor color2 = EnumUtils.valueOfEnum(NamedColor.class,0xFF00, NamedColor::getValue);

若不知道要匹配的值是什么类型,也可以把可能的getter都放进去:

NamedColor color3 = EnumUtils.valueOfEnum(NamedColor.class,obj, NamedColor::getName,NamedColor::getValue);
        

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章