Enum.valueOf(класс <T> enumType, String name) вопрос
Я пытаюсь обойти ошибку компиляции ( "Связанное несоответствие:..." ), относящееся к динамическому просмотру enum.
В основном я хочу добиться чего-то вроде этого:
String enumName = whatever.getEnumName();
Class<? extends Enum<?>> enumClass = whatever.getEnumClass();
Enum<?> enumValue = Enum.valueOf(enumClass, enumName);
Что бы я ни делал, я всегда получаю ошибку компиляции. Честно говоря, дженерики и перечисления для меня совершенно разные...
Что я здесь делаю неправильно?
Ответы
Ответ 1
Я думаю, что это не сработает точно так, как если бы вы не получили доступ к переменной типа (через подпись типа или метода). Проблема заключается в сигнатуре метода 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());
}
Вывод:
ЭЛВИС
Ответ 2
Проблема заключается в 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;
}
}
Но размышление грязно и очень редко, что вы хотите. Не делайте этого.
Ответ 3
На самом деле существует альтернативный подход: вы можете использовать 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
, но это тривиальная вещь для изменения.