考虑put
接口的java.util.Map
方法的规范。
它说:
@throws ClassCastException if the class of the specified key or value
prevents it from being stored in this map
Map
是一个通用接口,分别为关键对象和值对象提供两个类型参数: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,它们产生了相同的结果)。
答案 0 :(得分:1)
Map
是一个接口,它实质上为该接口的所有实现定义了一个契约。 Map.put
的文档告诉您,此方法可能会抛出ClassCastException
。这并不是要求所有实现抛出它。
如果您查看documentation for HashMap.put
,您会注意到它根本没有提到ClassCastException
。正如评论中所提到的,TreeMap.put
会抛出ClassCastException
,因为它需要能够准确地比较密钥。
如果您想要实现自己的java.util.Map
,那么如果您想限制键或值的类型,则可以抛出ClassCastException
,即使接口上的泛型无法强制执行碰巧使用原始的Map
类型。
我认为这只是Collections API的实现者说要小心。