决定不使用完全泛型的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)。
当前回答
兼容性。
在泛型可用之前,只有get(Object o)。
如果他们改变了这个方法来获得(<K> o),这可能会迫使java用户进行大量的代码维护,只是为了让正常的代码重新编译。
他们可以引入一个额外的方法,比如get_checked(<K> o),并弃用旧的get()方法,这样就有了一个更温和的过渡路径。但出于某种原因,这并没有做到。(我们现在所处的情况是,需要安装findBugs之类的工具来检查get()参数和map的声明键类型<K>之间的类型兼容性。)
我认为与.equals()的语义相关的参数是虚假的。(从技术上讲,他们是正确的,但我仍然认为他们是假的。如果o1和o2没有任何共同的超类,任何头脑正常的设计师都不会让o1.equals(o2)为真。)
其他回答
正如其他人所提到的,get()等不是泛型的原因是,您正在检索的条目的键不必与传递给get()的对象的类型相同;该方法的规范只要求它们相等。这源于equals()方法如何接受Object作为参数,而不仅仅是对象的相同类型。
Although it may be commonly true that many classes have equals() defined so that its objects can only be equal to objects of its own class, there are many places in Java where this is not the case. For example, the specification for List.equals() says that two List objects are equal if they are both Lists and have the same contents, even if they are different implementations of List. So coming back to the example in this question, according to the specification of the method is possible to have a Map<ArrayList, Something> and for me to call get() with a LinkedList as argument, and it should retrieve the key which is a list with the same contents. This would not be possible if get() were generic and restricted its argument type.
合同的表述如下:
更正式地说,如果这个映射包含 从键k到值v的映射 (key==null ?)k = =零: key。equals(k)),然后这个方法 返回v;否则返回null。 (最多可以有一个这样的 映射)。
(我的重点)
因此,成功的键查找取决于输入键对等式方法的实现。它不一定依赖于k的类。
兼容性。
在泛型可用之前,只有get(Object o)。
如果他们改变了这个方法来获得(<K> o),这可能会迫使java用户进行大量的代码维护,只是为了让正常的代码重新编译。
他们可以引入一个额外的方法,比如get_checked(<K> o),并弃用旧的get()方法,这样就有了一个更温和的过渡路径。但出于某种原因,这并没有做到。(我们现在所处的情况是,需要安装findBugs之类的工具来检查get()参数和map的声明键类型<K>之间的类型兼容性。)
我认为与.equals()的语义相关的参数是虚假的。(从技术上讲,他们是正确的,但我仍然认为他们是假的。如果o1和o2没有任何共同的超类,任何头脑正常的设计师都不会让o1.equals(o2)为真。)
我们正在做大的重构,我们错过了这个强类型的get(),以检查我们是否错过了旧类型的get()。
但是我发现了编译时间检查的变通/丑陋的技巧:创建Map接口,强类型get, containsKey, remove…然后放到java中。您的项目的Util包。
你只调用get()就会得到编译错误,…对于错误的类型,其他的编译器似乎都可以(至少在eclipse kepler内部)。
不要忘记在检查构建后删除此接口,因为这不是您在运行时想要的。
向后兼容,我想。Map(或HashMap)仍然需要支持get(Object)。