Enum.valueOf(Class <t> enumType,String name)问题</t>

时间:2010-10-25 11:32:43

标签: java generics reflection enums

我正在尝试解决与动态枚举查找相关的编译错误(“绑定不匹配:...”)。

基本上我想达到这样的目的:

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

无论我做什么,我总是以编译错误结束。老实说,仿制药和枚举对我来说是非常令人难以置信的......

我在这里做错了什么?

3 个答案:

答案 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,但这是一件很容易改变的事情。