Static methods in interfaces do not work, how to get a specific enumeration value from several enumerations?

I have a few enumerations that can be found using int. This is done by the static method for listing. For instance:

enum Foo { A, B, C, D, ... ; public static Foo fromInt(int i) { switch(i) { case 15: return A; case 42: return B; ... } } enum Bar { BLA, BOO, BEE, ... ; public static Bar fromInt(int i) { switch(i) { case 78: return BLA; case 22: return BOO; ... } } ... 

Now in some code I have a generic type T , which is guaranteed to be one of these enumerations, and I have an integer i . How can I call the fromInt method and get an enum instance with the value i ?

I tried to create an interface with a static fromInt method and let it list, but static methods do not work in interfaces.

I can not use Java 8.

+6
source share
3 answers

Short answer you cannot

Long answer, you can pass the Class this enumeration to your method and call fromInt by reflection or create a factory interface and implement it for each of your enumerations, and then pass the correct instance to your method.

+2
source

@ Talex answer extension :

Reflection:

 public class YourEnumFactory { public static <T extends Enum<T>> T get(Class<T> type,int i) { try { return (T) type.getDeclaredMethod("fromInt", int.class).invoke(null, i); } catch (Exception e) { throw new IllegalStateException("Could not find instance of '" + type + "' given '" + i + "'", e); } } } 

Factories:

 public class YourEnumFactory { private interface Factory<T> { T fromInt(int i); } private static final Map<Class<?>, Factory<?>> FACTORIES; static { Map<Class<?>, Factory<?>> factories = new HashMap<>(); factories.put(Foo.class, new Factory<Foo>() { @Override public Foo fromInt(int i) { return Foo.fromInt(i); } }); factories.put(Bar.class, new Factory<Bar>() { @Override public Bar fromInt(int i) { return Bar.fromInt(i); } }); FACTORIES = Collections.unmodifiableMap(factories); } public static <T extends Enum<T>> T get(Class<T> type, int i) { Factory<T> factory = (Factory<T>) FACTORIES.get(type); if (factory != null) { return factory.fromInt(i); } else { throw new InvalidParameterException("No factory for type '" + type + "'"); } } } 

As I always try to avoid reflection, I personally would choose the second solution.

0
source

You cannot do it this way, but I would do it like this:

 interface HasId() { public int getId(); } public class MyRegistry { private static Map<Class<?>, Map<Integer, Object>> REGISTRY = new HashMap<>(); public static <T extends HasId> T fromInt(int id, Class<T> clazz) { return clazz.cast(REGISTRY.getOrDefault(clazz, Collections.emptyMap()).get(id)); } public static void register(HasId obj) { REGISTRY.putIfAbsent(obj.getClass(), new HashMap<>()).put(obj.getId, obj); } } enum Foo implements HasId { A(15), B(42), C(86), D(99); private final int id; Foo(int id) { this.id = id; MyRegistry.register(this); } public int getId() { return id; } } // ditto for other enums or non enums as you like 

Then to use:

 Foo foo = MyRegistry.fromInt(15, Foo.class); // A 

Disclaimer: the code cannot compile or work because it was downloaded on my phone (but there is a reasonable chance that it will work)

0
source

All Articles