我遇到了一个奇怪的Java行为,看起来像个bug.是吗?将对象转换为泛型类型(例如K
),ClassCastException
即使对象不是实例,也不会抛出K
.这是一个例子:
import java.util.*;
public final class Test {
private static<K,V> void addToMap(Map<K,V> map, Object ... vals) {
for(int i = 0; i < vals.length; i += 2)
map.put((K)vals[i], (V)vals[i+1]); //Never throws ClassCastException!
}
public static void main(String[] args) {
Map<String,Integer> m = new HashMap<String,Integer>();
addToMap(m, "hello", "world"); //No exception
System.out.println(m.get("hello")); //Prints "world", which is NOT an Integer!!
}
}
Run Code Online (Sandbox Code Playgroud)
更新:感谢cletus和Andrzej Doyle提供的有用答案.因为我只能接受一个,所以我接受了Andrzej Doyle的回答,因为它让我找到了一个我认为不太糟糕的解决方案.我认为这是在单行中初始化小地图的一种更好的方法.
/**
* Creates a map with given …
Run Code Online (Sandbox Code Playgroud) static <T> void f1(Base arg1, T arg2) {
T loc = (T) arg1; // why Derived is "kind of cast" to String?
System.out.println(loc.getClass().getName()); // would print: Derived
}
f1(new Derived(), "sdf"); // T is String - inferred from arg2
class Base { }
class Derived extends Base { }
Run Code Online (Sandbox Code Playgroud)
我的想法是正确的:写作演员(T)意味着"编译器不能也不会检查这个演员".在编译时编译器不知道arg2会是什么(并且它可能是任何东西),因此编译器不能排除强制转换可以工作并且必须信任程序员.因此,在编译时永远不会检查此强制转换.在运行时,局部var声明看起来像Object loc = arg1;
(在类型擦除之后).所以一切正常,因为编译器从不关心这个(T)演员?
PS:我的研究:这个,这个.这也很有意思("将原语转换为通用":( T)true)我的问题更明确地指出问题,问题还在于编译器是否检查了演员(T)并且没有分心有问题的代码示例.