通用的任意值轉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);
        

 

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