Перечисления Java: десериализация произвольного перечисления из файла - PullRequest
4 голосов
/ 31 июля 2009

Сотрудник столкнулся с интересной проблемой сегодня, и хотя я думаю, что реальный, общий ответ - «тот факт, что у нас есть эта проблема, означает, что мы делаем что-то не так», я решил все равно спросите.

Учитывая следующее:

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);
  }
}

Я получаю следующую ошибку компиляции при вызове 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>>

Итак, мой вопрос: возможно ли, учитывая только строковое представление имени перечисляемого типа, а также .name () одного из его значений, получить ссылку на соответствующий объект перечислимого типа в виде Enum

Ответы [ 2 ]

9 голосов
/ 31 июля 2009

Ошибка компиляции говорит вам, что Class<?> не совпадает с Class<? extends Enum>. Попробуйте:

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

Обратите внимание, что вы получите непроверенное предупреждение о приведении, поэтому убедитесь, что className действительно представляет перечисление. Вы можете проверить, вызвав метод isEnum() объекта Class, например:

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);
}

Конечно, вы все равно получите необработанное предупреждение о типе на "new EnumeratedThing(value1)".

1 голос
/ 31 июля 2009

Просто приведите созданный вами класс, прежде чем вызывать метод, так что это соответствует сигнатуре метода:

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

Теперь этот класс рассматривается как подкласс Enum.

Примечание:

  • в любом случае это был правильный класс во время выполнения, но компилятор не знал
  • приведение типа: известный во время компиляции тип известен во время компиляции
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...