决定不使用完全泛型的get方法的原因是什么 在java.util接口中。地图< K、V >。

为了澄清问题,该方法的签名为

V get(对象键)

而不是

V get(K键)

我想知道为什么(同样的事情为remove, containsKey, containsValue)。


当前回答

向后兼容,我想。Map(或HashMap)仍然需要支持get(Object)。

其他回答

向后兼容,我想。Map(或HashMap)仍然需要支持get(Object)。

I was looking at this and thinking why they did it this way. I don't think any of the existing answers explains why they couldn't just make the new generic interface accept only the proper type for the key. The actual reason is that even though they introduced generics they did NOT create a new interface. The Map interface is the same old non-generic Map it just serves as both generic and non-generic version. This way if you have a method that accepts non-generic Map you can pass it a Map<String, Customer> and it would still work. At the same time the contract for get accepts Object so the new interface should support this contract too.

在我看来,他们应该添加一个新的接口,并在现有的集合上实现这两个接口,但他们决定支持兼容接口,即使这意味着get方法的设计更糟糕。注意,集合本身与现有方法兼容,只有接口不兼容。

我们正在做大的重构,我们错过了这个强类型的get(),以检查我们是否错过了旧类型的get()。

但是我发现了编译时间检查的变通/丑陋的技巧:创建Map接口,强类型get, containsKey, remove…然后放到java中。您的项目的Util包。

你只调用get()就会得到编译错误,…对于错误的类型,其他的编译器似乎都可以(至少在eclipse kepler内部)。

不要忘记在检查构建后删除此接口,因为这不是您在运行时想要的。

这是对波斯特尔定律的应用,“在你做的事情上要保守,在你接受别人的东西上要自由。”

无论类型如何,都可以执行相等性检查;equals方法定义在Object类上,并接受任何Object作为参数。因此,键等价和基于键等价的操作接受任何Object类型是有意义的。

当映射返回键值时,它通过使用类型参数尽可能多地保存类型信息。

我认为泛型教程的这一部分解释了这种情况(我的重点):

“你需要确保通用API没有过度限制;它必须 继续支持原API合同。再来看一些例子 从java.util.Collection。泛型前API看起来像这样:

interface Collection { 
  public boolean containsAll(Collection c);
  ...
}

一种天真的概括是:

interface Collection<E> { 
  public boolean containsAll(Collection<E> c);
  ...
}

虽然这肯定是类型安全的,但它不符合API的原始契约。 containsAll()方法适用于任何类型的传入集合。它只会 如果传入的集合真的只包含E的实例,则成功,但是:

传入的静态类型 收藏可能有所不同 因为调用者不知道 集合的精确类型 传入,或者因为它是 集合<S>,其中S是a E的子类型。 它是完美的 使用containsAll()调用是合法的 不同类型的集合。的 程序应该工作,返回false。”