gpt4 book ai didi

java - Generics Oddity - 我可以将一个 Long 值插入到 Map 中,它会编译并且不会在运行时失败

转载 作者:搜寻专家 更新时间:2023-10-30 19:43:07 26 4
gpt4 key购买 nike

输入以下代码:

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 发生位置的不同。

最佳答案

线

return (T)dataMap.get(value);

生成 Unchecked cast 警告,并且根据规范,任何此类警告的存在都会使您的代码类型不安全。 ClassCastException 发生在您第一次尝试将类型不安全的结果分配给错误类型的变量时,因为这是编译代码第一次进行类型检查。

请注意,Eclipse 的编译器插入的类型检查多于 JLS 强制要求的类型检查,因此,如果您在 Eclipse 中编译,hashMap.put 调用将失败并返回 CCE。编译器知道此调用必须有两个 String 参数,因此可以在实际方法调用之前插入类型检查。

正如您所猜测的那样,如果您将通用 T 替换为特定的 String,则类型检查会在此时发生——并且会失败。

关于java - Generics Oddity - 我可以将一个 Long 值插入到 Map<String, String> 中,它会编译并且不会在运行时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16611053/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com