为什么Collections.checkedMap和朋友不常用?

时间:2011-01-11 21:03:30

标签: java collections

我最近偶然发现了Collection.checkedMap系列函数的Javadoc,用于创建标准集合类型的动态类型安全视图。考虑到他们在诊断相对常见的程序员错误的集合之上添加了另一层安全性,我认为它们会更受欢迎。但是出于某些原因,在我参与过的所有大型Java项目中,我都没有看到它们被使用过一次。

我的问题是:Java程序员是否有更频繁地使用这些检查包装器的特殊原因?或者只是缺乏利益/缺乏对其存在的了解?

编辑:为了澄清我的问题,集合的通用版本仍然包含类型不安全的函数。例如,Map的{​​{1}},containsKeycontainsValueremove都会在get上运行。我的主要问题是,鉴于此类型不安全,为什么更多人不使用已检查的实现来诊断运行时类型违规。

2 个答案:

答案 0 :(得分:15)

这些类只有在滥用(或不使用)泛型时才真正需要。它在运行时检查时重复,应该足以在编译时通过泛型引擎的类型安全保证执行。

因此,在不信任库用户的API设计人员的上下文中使用这些方法只是非常有趣,并且希望保护自己或用户不正确地使用地图的用户。

以下是它的缺点:如果您的代码编译时没有原始类型警告或任何未经检查的转换/类型警告,那么保证 checked*方法不会给您带来任何好处;它们只是运行时命中。

修改

您似乎总结说,由于removeget等操作Object,因此它们在某种程度上是类型不安全的。他们不是。这些方法都不会将其操作数存储在地图中,因此您肯定不会损害地图本身的类型安全性。这些方法使用Object的一个主要原因是:为了向后兼容。从来没有任何严格的要求,要求坚持同一个班级。例如,如果类A的实例和类B的实例可能在某种程度上彼此相等,则将a放入地图然后调用remove(b) 应该删除{ {1}}的映射。

添加泛型后,需要支持此行为以保持向后兼容性。因此,他们无法将接口更新为a之类的内容,因为现有代码可能依赖于在给定完全不同类的实例的情况下删除映射。然而,它不是类型不安全的,并且使用已检查版本的地图不会稍微改变这种行为。

答案 1 :(得分:0)

RETRACT:以下观点是错误的。除了向后兼容性之外,还有一些很好的理由,为什么最好将查找索引设置为任何类型。

没有神圣的理由说明为什么这些方法必须采用Object代替E。在真实世界的程序中,如果传递非E对象,那几乎肯定是一个应用程序错误。在大多数情况下,E版API将优于Object版本。而且我说Sun在这里犯了一个错误。没有向后兼容性问题,因为通用API是一个全新的API。

幸运的是,如果我将非E类型传递给这些方法,我的IDE(IntelliJ)会警告我。静态检查已超出语言规范所述和编译器的作用。