2

Below is the failed attempt which I came up with, referring to Java Generic Enum class using Reflection.

Wanted to find a better way to do this. Couple of issues I find with this approach:

  • Each and every time I need to pass the class type. Example - EnumUtility.fromKey(Country.class, 1)

  • fromSet is duplicated in both City and Country

public enum City implements BaseEnumInterface {

    TOKYO(0), NEWYORK(1);

    private final int key;

    public static Set<Integer> fromValue(Set<City> enums) {
        return enums.stream().map(City::getKey).collect(Collectors.toSet());
    }

    public int getKey() {
        return key;
    }

    private City(int key) {
        this.key = key;
    }
}


public enum Country implements BaseEnumInterface {

    USA(0), UK(1);

    private final int key;

    public static Set<Integer> fromSet(Set<Country> enums) {
        return enums.stream().map(Country::getKey).collect(Collectors.toSet());
    }

    public int getKey() {
        return key;
    }

    private Country(int key) {
        this.key = key;
    }

}


public class EnumUtility {

    public static <E extends Enum<E> & BaseEnumInterface> E fromKey(Class<E> enumClass, Integer key) {
        for (E type : enumClass.getEnumConstants()) {
            if (key == type.getKey()) {
                return type;
            }
        }
        throw new IllegalArgumentException("Invalid enum type supplied");
    }

    public static <E extends Enum<E> & BaseEnumInterface> Set<Integer> fromSet(Class<E> enumClass, Set<E> enums) {
        return enums.stream().map(BaseEnumInterface::getKey).collect(Collectors.toSet());
    }   
}


interface BaseEnumInterface {

    int getKey();

}


public class EnumTester {

    public static void main(String args[]) {
        System.out.println(EnumUtility.fromKey(Country.class, 1));
    }
}
1
  • 1
    So why are your enums implementing an interface again? Commented May 10, 2017 at 14:43

1 Answer 1

3

There is no way to avoid passing in the enum class to fromKey. How else would you know which enum constants to check for the requested key? Note: The second parameter in that method should be of type int, not Integer. Using == on Integer instances will not compare numeric values, it will compare object references!

EnumUtility.fromSet should work fine, so each enum class does not need a fromSet method at all. Note that EnumUtility.fromSet does not need a Class argument at all, and in fact your code is not using that parameter.

Sign up to request clarification or add additional context in comments.

3 Comments

ok what about fromValue in each class City and Country ? Can I avoid duplication ?
City.fromValue and Country.fromSet are identical. When I refer to the fromSet method of each enum class, I am referring to both City.fromValue and Country.fromSet. Both of those methods are not needed.
Not only the Class parameter is obsolete. You can do it as simple as public static Set<Integer> fromSet(Set<? extends BaseEnumInterface> enums) { return enums.stream() .map(BaseEnumInterface::getKey) .collect(Collectors.toSet()); } which will accept any set of BaseEnumInterface sub-types, i.e. Set<City> or Set<Country>, it’s not even relevant whether they are enum types…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.