我正在尝试解决与动态枚举查找相关的编译错误(“绑定不匹配:...”)。
基本上我想达到这样的目的:
String enumName = whatever.getEnumName();
Class<? extends Enum<?>> enumClass = whatever.getEnumClass();
Enum<?> enumValue = Enum.valueOf(enumClass, enumName);
无论我做什么,我总是以编译错误结束。老实说,仿制药和枚举对我来说是非常令人难以置信的......
我在这里做错了什么?
答案 0 :(得分:28)
我认为除非您有权访问类型变量(通过类型或方法签名),否则它将无法正常工作。问题是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
答案 1 :(得分:23)
问题在于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;
}
}
但是反思是肮脏的,很少你想要的。不要这样做。
答案 2 :(得分:6)
实际上还有另一种方法:您可以使用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
,但这是一件很容易改变的事情。