Enum.valueOf (Class <T>enumType, String name) вопрос - PullRequest
33 голосов
/ 25 октября 2010

Я пытаюсь обойти ошибку компиляции ("Bound mismatch: ..."), относящуюся к динамическому поиску enum.

В основном я хочу добиться чего-то вроде этого:

String enumName = whatever.getEnumName();
Class<? extends Enum<?>> enumClass = whatever.getEnumClass();
Enum<?> enumValue = Enum.valueOf(enumClass, enumName);

Что бы я ни делал, я всегда получаю эту ошибку компиляции.Честно, дженерики и перечисления для меня просто ошеломляют ...

Что я здесь не так делаю?

Ответы [ 3 ]

28 голосов
/ 25 октября 2010

Я думаю, что это не будет работать точно так же, если у вас нет доступа к переменной типа (через сигнатуру типа или метода). Проблема заключается в методе подписи Enum.valueOf:

public static <T extends Enum<T>> T valueOf(
    Class<T> enumType,
    String name
);

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

public enum King{
    ELVIS
}

@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(final String[] args){
    final Class<? extends Enum> enumType = King.class;
    final Enum<?> theOneAndOnly = Enum.valueOf(enumType, "ELVIS");
    System.out.println(theOneAndOnly.name());
}

Выход:

ELVIS

23 голосов
/ 25 октября 2010

Проблема с Class<? extends Enum<?>>. Мы хотим E extends Enum<E>, но мы не можем этого получить, потому что у нас есть два разных подстановочных знака.

Итак, нам нужно ввести общий параметр, который можно ввести, вызвав метод:

enum MyEnum {
    ME;
}

public class EnName {
    public static void main(String[] args) {
        Enum<?> value = of(MyEnum.class, "ME");
        System.err.println(value);
    }
    private static <E extends Enum<E>> E of(Class<E> clazz, String name) {
        E value = Enum.valueOf(clazz, name);
        return value;
    }
}

Но отражение - это грязно и очень редко то, что вы хотите. Не делай этого.

6 голосов
/ 24 февраля 2015

На самом деле есть альтернативный подход: вы можете использовать Class.getEnumConstants и накатить свою собственную реализацию Enum.valueOf, у которой нет проблем такого же типа.Недостатком является то, что вы получаете общий Enum<?> - но если бы вы знали, какой у вас тип, вы все равно могли бы использовать Enum.valueOf.

private static Enum<?> findEnumValue(Class<? extends Enum<?>> enumType, String value) {
    return Arrays.stream(enumType.getEnumConstants())
                 .filter(e -> e.name().equals(value))
                 .findFirst()
                 .orElse(null);
}

(Обратите внимание, что моя версия возвращает null, если такой константы нет, вместо того, чтобы выдавать IllegalArgumentException, но это тривиальная вещь для изменения.

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