给出以下代码:
public static void main(String[] args) {
HashMap<String, String> hashMap = new HashMap<>();
HashMap<String, Object> dataMap = new HashMap<>();
dataMap.put("longvalue", 5L);
class TestMethodHolder {
<T> T getValue(Map<String, Object> dataMap, String value) {
return (T)dataMap.get(value);
}
}
hashMap.put("test", new TestMethodHolder().<String>getValue(dataMap, "longvalue"));
String value = hashMap.get("test"); // ClassCastException occurs HERE
System.out.println(value);
}
这段代码可以编译,这对我来说并不奇怪,而是 ClassCastException 发生在 get 行而不是它上面的 put 行,尽管我对可能发生的事情有一个有根据的猜测。由于泛型类型在运行时被擦除,因此 getValue() 中的强制转换实际上永远不会在运行时发生,并且实际上是对 Object 的强制转换。如果该方法将按如下方式实现,则运行时强制转换将发生并且它将在 put 行上失败(如预期的那样)。谁能证实这一点?
class TestMethodHolder {
String getValue(Map<String, Object> dataMap, String value) {
return (String)dataMap.get(value);
}
}
这是使用泛型的已知缺陷还是奇怪?那么在调用方法时使用 <> 表示法是不好的做法吗?
编辑:我使用的是默认的 Oracle JDK 1.7_03。
上面的另一个隐含问题:原始 getValue 中的转换是否仍然在运行时发生,但转换实际上是对 Object - 或者编译器是否足够聪明,可以完全避免在运行时不发生这种转换?这可能解释了人们在运行 ClassCastException 时注意到的发生位置的差异。