决定不使用完全泛型的get方法的原因是什么 在java.util接口中。地图< K、V >。
为了澄清问题,该方法的签名为
V get(对象键)
而不是
V get(K键)
我想知道为什么(同样的事情为remove, containsKey, containsValue)。
决定不使用完全泛型的get方法的原因是什么 在java.util接口中。地图< K、V >。
为了澄清问题,该方法的签名为
V get(对象键)
而不是
V get(K键)
我想知道为什么(同样的事情为remove, containsKey, containsValue)。
当前回答
合同的表述如下:
更正式地说,如果这个映射包含 从键k到值v的映射 (key==null ?)k = =零: key。equals(k)),然后这个方法 返回v;否则返回null。 (最多可以有一个这样的 映射)。
(我的重点)
因此,成功的键查找取决于输入键对等式方法的实现。它不一定依赖于k的类。
其他回答
这是对波斯特尔定律的应用,“在你做的事情上要保守,在你接受别人的东西上要自由。”
无论类型如何,都可以执行相等性检查;equals方法定义在Object类上,并接受任何Object作为参数。因此,键等价和基于键等价的操作接受任何Object类型是有意义的。
当映射返回键值时,它通过使用类型参数尽可能多地保存类型信息。
谷歌的一名出色的Java编码器Kevin Bourrillion不久前在一篇博客文章中就这个问题写了一篇文章(当然是在Set而不是Map的上下文中)。最相关的句子:
的方法 Collections框架(和谷歌. Collections框架) 收藏图书馆也是)从不 限制其参数的类型 除非是为了预防 收集从破碎。
我不完全确定我是否同意这一原则——例如,. net似乎需要正确的键类型就可以了——但值得遵循博客文章中的推理。(提到。net之后,有必要解释一下,为什么在。net中它不是问题的部分原因是。net中存在更大的问题,即更有限的方差…)
原因是包含是由equals和hashCode决定的,它们是Object上的方法,并且都接受Object参数。这是Java标准库的早期设计缺陷。再加上Java类型系统中的限制,它强制依赖于equals和hashCode的任何东西接受Object。
在Java中获得类型安全哈希表和相等性的唯一方法是避免使用Object。equals和Object。hashCode并使用通用的替代品。函数式Java提供的类型类就是为了这个目的:Hash<A>和Equal<A>。提供了HashMap<K, V>的包装器,在其构造函数中接受Hash<K>和Equal<K>。因此,该类的get和contains方法采用类型为K的泛型参数。
例子:
HashMap<String, Integer> h =
new HashMap<String, Integer>(Equal.stringEqual, Hash.stringHash);
h.add("one", 1);
h.get("one"); // All good
h.get(Integer.valueOf(1)); // Compiler error
我们正在做大的重构,我们错过了这个强类型的get(),以检查我们是否错过了旧类型的get()。
但是我发现了编译时间检查的变通/丑陋的技巧:创建Map接口,强类型get, containsKey, remove…然后放到java中。您的项目的Util包。
你只调用get()就会得到编译错误,…对于错误的类型,其他的编译器似乎都可以(至少在eclipse kepler内部)。
不要忘记在检查构建后删除此接口,因为这不是您在运行时想要的。
合同的表述如下:
更正式地说,如果这个映射包含 从键k到值v的映射 (key==null ?)k = =零: key。equals(k)),然后这个方法 返回v;否则返回null。 (最多可以有一个这样的 映射)。
(我的重点)
因此,成功的键查找取决于输入键对等式方法的实现。它不一定依赖于k的类。