Getting enum name based on value java in run time

mohan :

I need to get the enum name based on value. I am given with enum class and value and need to pick the corresponding name during run time .

I have a class called Information as below.

class Information {
    private String value;
    private String type;
    private String cValue;
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getcValue() {
        return cValue;
    }
    public void setcValue(String cValue) {
        this.cValue = cValue;
    }
    public static void main(String args[]) {
        Information inf = new Information();
        inf.setType("com.abc.SignalsEnum");
        inf.setValue("1");
    }
}

class SignalEnum {
    RED("1"), GREEN("2"), ORANGE("3");
    private String sign;
    SignalEnum(String pattern) {
        this.sign = pattern;
    }
}
class MobileEnum {
    SAMSUNG("1"), NOKIA("2"), APPLE("3");
    private String mobile;
    MobileEnum(String mobile) {
        this.mobile = mobile;
    }
}

In run time i will come to know the enum name using the attribute type from the Information class and also i am getting the value. I need to figure out the corresponding enum to set the value for cValue attribute of Information class.

Just for example i have provided two enums like SignalEnum and MobileEnum but in my actual case i will get one among 100 enum types. Hence i dont want to check type cast. I am looking for some solution using reflection to se the cValue.

Nikolai Shevchenko :

Here is a simple resolver for any enum class. Since reflection operations are expensive, it's better to prepare all required data once and then just query for it.

class EnumResolver {

    private Map<String, Enum> map = new ConcurrentHashMap<>();

    public EnumResolver(String className) {
        try {
            Class enumClass = Class.forName(className);

            // look for backing property field, e.g. "sign" in SignalEnum
            Field accessor = Arrays.stream(enumClass.getDeclaredFields())
                    .filter(f -> f.getType().equals(String.class))
                    .findFirst()
                    .orElseThrow(() -> new NoSuchFieldException("Not found field to access enum backing value"));

            accessor.setAccessible(true);

            // populate map with pairs like ["1" => SignalEnum.RED, "2" => SignalEnum.GREEN, etc]
            for (Enum e : getEnumValues(enumClass)) {
                map.put((String) accessor.get(e), e);
            }

            accessor.setAccessible(false);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    public Enum resolve(String backingValue) {
        return map.get(backingValue);
    }

    private <E extends Enum> E[] getEnumValues(Class<E> enumClass) throws ReflectiveOperationException {
        Field f = enumClass.getDeclaredField("$VALUES");
        f.setAccessible(true);
        Object o = f.get(null);
        f.setAccessible(false);
        return (E[]) o;
    }
}

And here is simple JUnit test

public class EnumResolverTest {

    @Test
    public void testSignalEnum() {
        EnumResolver signalResolver = new EnumResolver("com.abc.SignalEnum");
        assertEquals(SignalEnum.RED, signalResolver.resolve("1"));
        assertEquals(SignalEnum.GREEN, signalResolver.resolve("2"));
        assertEquals(SignalEnum.ORANGE, signalResolver.resolve("3"));
    }

    @Test
    public void testMobileEnum() {
        EnumResolver mobileResolver = new EnumResolver("com.abc.MobileEnum");
        assertEquals(MobileEnum.SAMSUNG, mobileResolver.resolve("1"));
        assertEquals(MobileEnum.NOKIA, mobileResolver.resolve("2"));
        assertEquals(MobileEnum.APPLE, mobileResolver.resolve("3"));
    }
}

And again for performance sake you can also instantiate these various resolvers once and put them into a separate Map

Map<String, EnumResolver> resolverMap = new ConcurrentHashMap<>();
resolverMap.put("com.abc.MobileEnum", new EnumResolver("com.abc.MobileEnum"));
resolverMap.put("com.abc.SignalEnum", new EnumResolver("com.abc.SignalEnum"));
// etc

Information inf = new Information();
inf.setType("com.abc.SignalsEnum");
inf.setValue("1");

SignalEnum red = (SignalEnum) resolverMap.get(inf.getType()).resolve(inf.getValue());

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=161730&siteId=1
Recommended