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));
    }
}
Community
  • 1
  • 1
shoaib1992
  • 410
  • 1
  • 8
  • 26

1 Answers1

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.

VGR
  • 40,506
  • 4
  • 48
  • 63
  • ok what about fromValue in each class City and Country ? Can I avoid duplication ? – shoaib1992 May 10 '17 at 15:42
  • 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. – VGR May 10 '17 at 15:57
  • 2
    Not only the `Class` parameter is obsolete. You can do it as simple as `public static Set 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` or `Set`, it’s not even relevant whether they are `enum` types… – Holger May 10 '17 at 16:37