如果我在编译时不知道该类,如何获取Enum的值?

时间:2011-03-10 15:46:21

标签: java generics reflection enums

我正在尝试执行以下操作:

Class<?> cls = unknownClass;
if(cls.isEnum()){
    @SuppressWarnings("unchecked")
    Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) cls;
    Object val = Enum.valueOf(enumClass, "NAME1");
}

但是我收到以下错误:

Bound mismatch: The generic method valueOf(Class<T>, String) of type Enum<E> is 
not applicable for the arguments (Class<capture#5-of ? extends Enum<?>>, String). 
The inferred type capture#5-of ? extends Enum<?> is not a valid substitute for 
the bounded parameter <T extends Enum<T>>   

有人能告诉我我做错了吗?

5 个答案:

答案 0 :(得分:20)

鉴于演员不会真的正在检查事情,我会选择完全原始的版本:

if (cls.isEnum()){
    @SuppressWarnings("unchecked")
    Object val = Enum.valueOf(cls, "NAME1");
}

这似乎有效。完整的例子:

public class Test
{
    enum Foo
    {
        BAR, BAZ
    }


    public static void main(String[] args)
    {
        @SuppressWarnings("rawtypes")
        Class cls = Foo.class;

        if (cls.isEnum())
        {        
            @SuppressWarnings("unchecked")
            Object value = Enum.valueOf(cls, "BAR");
            System.out.println(value);
        }
    }
}

答案 1 :(得分:7)

问题是你有两个?,它们可能不同,而且它们必须相同。

您必须使用非泛型声明类似

的泛型类型
public static <T extends Enum<T>> T val(Class<T> cls) {
    if(cls.isEnum()) { // is redundant when the compiler checks this.
        @SuppressWarnings("unchecked")
        Class<T> enumClass = (Class<T>) cls;
        T val = Enum.valueOf(enumClass, "NAME1");
        return val;
    }
    return null;
}

然而,调用这种方法也是一个噩梦。 ;)

答案 2 :(得分:4)

Class.getEnumConstants将提供所有枚举,然后您就可以找到您感兴趣的枚举。

修改Jon的代码:

public class Test {
    private enum Foo {
        BAR, BAZ
    } 

    public static void main(String[] args) {
        Class<?> cls = Foo.class;

        if (cls.isEnum()) { 
            for (Object constant : cls.getEnumConstants()) { 
                Enum<?> enumConstant = (Enum<?>)constant;
                if (enumConstant.name().equals("BAR")) {
                    System.out.println(constant);
                    break;
                }
            }
        }
    }
}

在Java SE 8中,您可能能够使用lambda和抽象控制流来做一些聪明的事情。

注意:

  • 反思几乎总是一个非常糟糕的主意。
  • 无需检查未经检查的警告或抑制这些有效警告。
  • 无需使用rawtypes(有拼写和语义)警告或抑制这些有效警告。
  • 不需要毫无根据的咆哮。
  • 无需回答这个问题。

答案 3 :(得分:1)

使用原始类型是好的。虽然Java不愿意添加原始类型,但除了向后兼容性问题之外,它已被证明是必要且必不可少的。

如果没有原始类型,要以理论上完美的方式解决您的问题,Java必须更加复杂。它可能需要一个类型变量变量。那时,代码不再取悦人类,而是取悦机器。 (考虑到所有无法理解的泛型代码,我们可能已经在这一点上了)

答案 4 :(得分:-1)

    class EnumValues<P extends Enum<P>>
    {
        public static <P extends Enum<P>> P [] getValues( Class<P> keyType)
        {
            return keyType.getEnumConstants();
        }
    }

用法:

    Class cls = Thread.State.class;
    for( Enum en : EnumValues.getValues( cls)) 
        System.out.println( en.name());