考虑 put
的规范java.util.Map
的方法界面。
它说:
@throws ClassCastException if the class of the specified key or value
prevents it from being stored in this map
Map
是具有两个类型参数 的通用接口(interface):K
和V
用于键对象和值对象分别。 put
方法签名是:
V put(K key, V value);
在什么情况下调用此方法可能会在运行时导致 ClassCastException
?
我认为如果存在一些泛型和原始类型的混合,那么在忽略编译器警告的同时,这可能会发生。因此,在重读 Effective Java 2 之后,我根据 unsafeAdd
示例(项目 #23,第 112 页)对以下内容进行了建模:
public class MapClassCastException {
public static void main(String[] args) {
Map<Integer, String> m = new HashMap<>();
unsafePut(m);
System.out.println(m.get(1));
}
private static void unsafePut(Map m) { // beware: Raw Type
m.put("blow", "up");
m.put(new int[]{2, 4}, "xxx");
}
}
但这段代码不会在运行时因 ClassCastException
而失败,而是打印 null
。 (当然,我忽略编译器警告只是为了更好地理解它)。
有人可以演示 Map#put
如何在运行时抛出 ClassCastException
吗? (我在 JDK 1.6、1.7 和 1.8 上尝试过,它们产生了相同的结果)。
最佳答案
Map
是一个接口(interface),它实质上为该接口(interface)的所有实现定义了一个契约。 Map.put
的文档告诉您此方法可能会抛出 ClassCastException
。这并不要求所有实现都抛出它。
如果您查看 documentation for HashMap.put
,您会注意到它根本没有提到 ClassCastException
。如评论中所述,TreeMap.put
确实会抛出 ClassCastException
,因为它需要能够准确地比较键。
如果您想实现自己的 java.util.Map
,如果您想限制键或值的类型,则可以抛出 ClassCastException
,即使如果您碰巧使用原始 Map
类型,则接口(interface)上的泛型无法强制执行。
我认为这只是 Collections API 的实现者所说的要小心。
关于java - 为什么 Map#put 指定@throws ClassCastException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42603687/