Java Enum.valueOf(Class<T> enumType, String name) 问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4014117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Enum.valueOf(Class<T> enumType, String name) question
提问by Tom
I am trying to get around a compile error ("Bound mismatch: ...") relating to dynamic enum lookup.
我正在尝试解决与动态枚举查找相关的编译错误(“绑定不匹配:...”)。
Basically I want to achieve something like this:
基本上我想实现这样的目标:
String enumName = whatever.getEnumName();
Class<? extends Enum<?>> enumClass = whatever.getEnumClass();
Enum<?> enumValue = Enum.valueOf(enumClass, enumName);
Whatever I do, I always end up with that compile error. Honestly, generics and enums are quite mindboggling to me...
无论我做什么,我总是以编译错误告终。老实说,泛型和枚举对我来说非常令人难以置信......
What am I doing wrong here?
我在这里做错了什么?
采纳答案by Sean Patrick Floyd
I think it won't work exactly like this unless you have access to a type variable (through either a type or method signature). The problem is the method signature of Enum.valueOf
:
我认为除非您可以访问类型变量(通过类型或方法签名),否则它不会完全像这样工作。问题是方法签名Enum.valueOf
:
public static <T extends Enum<T>> T valueOf(
Class<T> enumType,
String name
);
There's no way to get a T without a type variable. But you can do it like this if you're willing to suppress some compiler warnings:
没有类型变量就无法获得 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());
}
Output:
输出:
ELVIS
猫王
回答by Tom Hawtin - tackline
The problem is with Class<? extends Enum<?>>
. We want E extends Enum<E>
, but we can't get that because we have two distinct wildcards.
问题在于Class<? extends Enum<?>>
. 我们想要E extends Enum<E>
,但我们无法得到它,因为我们有两个不同的通配符。
So we need to introduce a generic parameter, possible introduced by calling a method:
所以我们需要引入一个泛型参数,可能通过调用一个方法来引入:
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;
}
}
But reflection is mucky and very rarely what you want. Don't do it.
但是反射是肮脏的,而且很少是你想要的。不要这样做。
回答by Sbodd
There's actually an alternate approach: you can use Class.getEnumConstants
and roll your own implementation of Enum.valueOf
that doesn't have the same type problems. The downside is you get back a generic Enum<?>
- but if you knew what type you had coming in, you would be able to use Enum.valueOf
anyway.
实际上有一种替代方法:您可以使用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);
}
(Note that my version returns null
if there's no such constant rather than throwing an IllegalArgumentException
, but that's a trivial thing to change.
(请注意,null
如果没有这样的常量而不是抛出,我的版本会返回IllegalArgumentException
,但这是一个微不足道的改变。