我有一个参数化值,在运行时解决:
public class GenericsMain {
public static void main(String... args) {
final String tag = "INT";
Field field = resolve(tag);
if (tag.equals("INT")) {
/*
In here I am using the "secret knowledge" that if tag equals INT, then
field could be casted to Field<Integer>. But at the same time I see an unchecked cast
warning at here.
Is there a way to refactor the code to be warning-free?
*/
Field<Integer> integerField = (Field<Integer>) field;
foo(integerField);
}
}
public static Field resolve(String tag) {
switch (tag) {
case "INT":
return new Field<>(1);
case "DOUBLE":
return new Field<>(1.0d);
default:
return null;
}
}
public static <T> void foo(Field<T> param) {
System.out.println(param.value);
}
static class Field<T> {
public final T value;
public Field(T value) {
this.value = value;
}
}
}
有没有办法在上面的代码中避免未经检查的演员(标有长评论)?
答案 0 :(得分:6)
通常,没办法,因为类型参数绑定到声明。您要做的是根据运行时值更改静态声明。
但是,您可以通过声明添加类型参数
的参数化方法来最小化未选中的强制转换区域@SuppressWarnings("unchecked")
private static <T> Field<T> asParameterized(Field<?> field) {
return (Field<T>) field;
}
然后使用
Field<Integer> intField = GenericsMain.<Integer> asParameterized(field);
答案 1 :(得分:3)
您可以使用注释来执行此操作。使用以下注释:
@SuppressWarnings("unchecked")
答案 2 :(得分:3)
也许。您可以使用对类型信息进行编码的类型,而不是哑字符串标记。请参阅此博文:http://blog.pdark.de/2010/05/28/type-safe-object-map/
public class FieldKey<T> {
private String name;
public FieldKey(String name) {
this.name = name;
}
public String name() {
return name;
}
}
并将Field
的构造函数更改为public Field(FieldKey<T> key, T value)
。
你仍然必须进行投射,但编译时间检查将确保它们永远不会失败。
答案 3 :(得分:1)
所有答案都很好,但我认为没有足够强调为什么你会收到警告并且正在施展。
您通过执行未经检查的强制转换来明确规避类型系统。通过说&#34;我有关于这种类型的信息,编译器无法获得&#34; - 你告诉你更了解的编译器。
这当然是一个可能和合理的用例:否则这些强制转换是不允许的,但警告是好的,因为它表明你应该确实确定类型是什么。
这很有道理。事实上,如果您检查像GSON这样的序列化库,那么它们就是full of these warnings and supressions。
不要担心你的代码 - 一切都很好。如果有办法去&#34;欺骗&#34;另一方面编译器不发出本来应该是严重问题的警告:)