这必须是一些小东西,但我不明白。
当它具有与Enum
的valueOf
完全相同的泛型声明时,为什么会导致未检查的强制转换编译器警告?
public static final <T extends Enum<T>> Enum toValue(T for_value, String value) {
try {
return Enum.<T>valueOf((Class<T>)for_value.getClass(), value);
} catch(RuntimeException rx) {
throw new IllegalArgumentException(value);
}
}
编译器警告:
R:jeffyprogrammingsandboxxbnjavaxbnutilEnumUtil.java:92:
warning: [unchecked] unchecked cast
Enum.<T>valueOf((Class<T>)for_value.getClass(), value);
^
required: Class<T>
found: Class<CAP#1>
where T is a type-variable:
T extends Enum<T> declared in method <T>toValue(T,String,String)
where CAP#1 is a fresh type-variable:
CAP#1 extends Enum from capture of ? extends Enum
R:jeffyprogrammingsandboxxbnjavaxbnutilEnumUtil.java:98: error: missing return statement
}
^
1 error
1 warning
它也发生在从函数调用中删除一个或两个泛型中,例如
Enum.valueOf(for_value.getClass(), value);
这是我发现的最接近的问题:Enum.valueOf为扩展Enum的未知类型的类抛出警告。此枚举的类型是已知的。
您应该调用getDeclaringClass()
,它还将修复泛型问题(指定返回Class<T>
)。在定义了自己方法的枚举常量上调用getClass()
实际上可以返回与枚举类型不同的类。
Object.getClass()
的JavaDocs指定:
实际的结果类型是Class,其中|X|是对调用getClass的表达式的静态类型的擦除。
泛型类型T
的擦除是Object
,因此for_value.getClass()
的返回类型是Class<? extends Object>
,而不是Class<T>
。尝试将其强制转换为Class<T>
会给您未检查的强制转换警告。
生成未检查警告的是getClass
调用,而不是Enum#valueOf
。原因是getClass
返回的是Class<? extends T>
而不是Class<T>
。请记住,for_value
实际上可能是T
的一个子类。
然而;
虽然getClass
被声明为返回Class<?>
,但它的规范是特殊情况,您可以将其结果分配给Class<? extends T>
,而不需要显式类:
实际结果类型为
Class<? extends |X|>
。。。
这很好,但第一个问题是它返回X
的擦除,这意味着原始类型。因此,下面的赋值需要一个未检查的强制转换:
@SuppressWarnings("unchecked")
Class<? extends E> cls = (Class<? extends E>)for_value.getClass();
由于Enum的语言限制,这样做是安全的:不可能用一个会破坏这一点的声明来创建一个枚举。
不幸的是,因为Enum有递归泛型(E extends Enum<E>
),所以通配符不好,所以您不能用它调用valueOf
当我编辑这篇文章时,有人发布了正确的答案,那就是使用Enum#getDeclaringClass
。