Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Enums: de-serializing an arbitrary enum from a file

A co-worker ran into an interesting issue today, and while I think the actual, big-picture answer is "the fact that we're having this problem means we're doing something wrong", I figured I'd ask this anyway.

Given the following:

public class CrazyEnumTest {

  public class EnumeratedThing<T extends Enum<T>> {
    public T myValue;

    public EnumeratedThing(T value) {
      myValue = value;
    }
  }

  public static void main (String[] args) {
    String className = args[0];
    String enumValue = args[1];

    Enum<?> value1 = Enum.valueOf(Class.forName(className), enumValue);
    EnumeratedThing<?> thing1 = new EnumeratedThing(value1);
  }
}

I get the following compile error on the call to Enum.valueOf:

Bound mismatch: The generic method valueOf(Class<T>, String) of type Enum<E> is not applicable for the arguments (Class<capture#1-of ?>, String). The inferred type capture#1-of ? is not a valid substitute for the bounded parameter <T extends Enum<T>>

So, my question is: is it possible to, given only the String representation of a enumerated type name as well as the .name() of one of its values, get a reference to the corresponding enumerated type object as an Enum?

like image 626
Sbodd Avatar asked Dec 29 '22 18:12

Sbodd


1 Answers

The compile error is telling you that Class<?> is not the same as Class<? extends Enum>. Try:

Enum<?> value1 =
        Enum.valueOf((Class<? extends Enum>) Class.forName(className), enumValue);

Note that you'll get an unchecked cast warning, so make sure that className actually does represent an enum. You could check by calling the isEnum() method on the Class object, like this:

Class<?> enumClass = Class.forName(className);
if (enumClass.isEnum()) {
    @SuppressWarnings("unchecked") // we just checked it, so it had better work
    Enum<?> value1 = Enum.valueOf((Class<? extends Enum>) enumClass, enumValue);
    EnumeratedThing<?> thing1 = new EnumeratedThing(value1);
}

Of course, you'll get a raw type warning on "new EnumeratedThing(value1)" anyway.

like image 130
Michael Myers Avatar answered Jan 06 '23 05:01

Michael Myers