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