这必须是小事,但我没有得到它。
为什么这会导致未经检查的强制转换编译器警告,因为它与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:\jeffy\programming\sandbox\xbnjava\xbn\util\EnumUtil.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:\jeffy\programming\sandbox\xbnjava\xbn\util\EnumUtil.java:98: error: missing return statement
}
^
1 error
1 warning
也会在函数调用中删除一个或两个泛型,例如
Enum.valueOf(for_value.getClass(), value);
这是我发现的最接近的问题: Enum.valueOf throws a warning for unknown type of class that extends Enum? 。这个枚举的类型是已知的。
答案 0 :(得分:8)
您应该调用getDeclaringClass()
,这也将修复泛型问题(指定返回Class<T>
)。使用自己定义的方法在枚举常量上调用getClass()
实际上可以从枚举类型返回不同的类。
答案 1 :(得分:1)
getClass
调用是生成未经检查的警告,而不是Enum#valueOf
。原因是getClass
返回Class<? extends T>
而不是Class<T>
。请记住,for_value
实际上可能是T
的子类。
然而;
虽然宣布getClass
返回Class<?>
,但规范却是you can assign the result of it to a Class<? extends T>
without the explicit class:
实际结果类型为
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
的正确答案。
答案 2 :(得分:1)
JavaDocs for Object.getClass()
指定:
实际结果类型是Class,其中| X |是擦除调用getClass的表达式的静态类型。
通用类型T
的{{3}}为Object
,因此for_value.getClass()
的返回类型为Class<? extends Object>
,不是 Class<T>
。试图将其投射到Class<T>
是为了给你未经检查的投射警告。