Java 如果我没有';我在编译时不知道这个类?

Java 如果我没有';我在编译时不知道这个类?,java,generics,reflection,enums,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"); }

我正在努力做到以下几点:

Class<?> cls = unknownClass;
if(cls.isEnum()){
    @SuppressWarnings("unchecked")
    Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) cls;
    Object val = Enum.valueOf(enumClass, "NAME1");
}
Class cls=未知类;
if(cls.isEnum()){
@抑制警告(“未选中”)
类>枚举类=(类>)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>>   
绑定不匹配:Enum类型的泛型方法valueOf(Class,String)为
不适用于参数(类鉴于演员阵容不会真正检查东西,我会选择完全原始的版本:

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);
        }
    }
}

问题是您有两个
,它们可能不同,但必须相同

您要么必须使用非泛型,要么声明泛型类型,如

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;
}
公共静态T值(类别cls){
编译器检查时,if(cls.isEnum()){//是冗余的。
@抑制警告(“未选中”)
类枚举类=(类)cls;
T val=Enum.valueOf(enumClass,“NAME1”);
返回val;
}
返回null;
}

然而,调用此方法也有点像噩梦。

类。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;
                }
            }
        }
    }
}
公共类测试{
私有枚举Foo{
巴兹酒吧
} 
公共静态void main(字符串[]args){
类别cls=Foo.Class;
如果(cls.isEnum()){
对于(对象常量:cls.getEnumConstants()){
枚举常量=(枚举)常量;
if(enumConstant.name().equals(“BAR”)){
系统输出println(常数);
打破
}
}
}
}
}
在JavaSE8中,您可能能够使用lambda和抽象控制流做一些聪明的事情

注:

  • 反思几乎总是一个非常糟糕的主意
  • 无需取消选中警告或抑制这些有效警告
  • 不需要rawtypes(它的拼写和语义)警告或抑制那些有效的警告
  • 不需要毫无根据的咆哮
  • 没有必要否决这个答案

    • 使用原始类型是好的。虽然Java不愿意添加原始类型,但事实证明,除了向后兼容性问题之外,它是必要的和不可或缺的


      如果没有原始类型,要以理论上完美的方式解决问题,Java必须更加复杂。它可能需要一个类型变量。在这一点上,代码不再是为了取悦人类,而是取悦机器。(考虑到所有不可能理解的泛型代码,我们可能已经到了这一步)
      T
      被定义为一个扩展
      Enum
      的类,这是由于Enum对
      公共类Enum
      的繁琐/递归声明造成的。Peter:是的,但它将被完全删除,因为调用者无法与T交互。正如您所写的,我如何调用该方法?:)您可以简单地调用
      val(MyEnum.class)
      ,但是编译器在确定返回类型时可能会感到困惑,因为它不受某个参数的约束,因此您最终会编写
      MyClass.val(MyEnum.class)
      在一个更合理的示例中,您不需要检查isEnum()V=T及其简单得多。您必须将其转换为
      (类)
      @dacwe:它在我的编译器上工作-但您没有说它以什么方式不工作。我将展示一个简短但完整的示例…啊,对不起,它没有编译<代码>类cls=SomeEnum.Class;Object val=Enum.valueOf(cls,“NAME1”)和我得到一个类似的
      绑定不匹配
      作为询问者。@dacwe:您没有向我们展示
      cls的声明
      。只需将其更改为原始类型
      Class
      ,而不是
      Class
      。有关完整示例,请参见我的编辑。(如果无法更改
      cls
      的声明,请使用
      @SuppressWarnings(“rawtypes”)类clazz=cls;
      然后改为使用
      clazz
      。使用原始类型调用泛型方法有点顽皮。实际上,那里有一个未经检查的强制转换。最近的编译器会给你警告(注意他们!)(顺便说一句,不是我的否决票。)我喜欢这样,如果我在编译时不知道枚举类型,这个解决方案不会抛出编译器警告。我可以只拥有一个foo类型的实例,调用fooInstance.getClass()并将其用于cls。
          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());