有什么区别? 和Java中的对象generics?

我正在使用Eclipse来帮助我清理一些代码,以正确使用Javagenerics。 大多数情况下,它在推断types方面做得非常出色,但在某些情况下,推断types必须尽可能通用:对象。 但是Eclipse似乎给了我一个在Objecttypes和'?'types之间进行select的选项。

那么有什么区别:

HashMap<String, ?> hash1; 

 HashMap<String, Object> hash2; 

HashMap<String, String>一个实例匹配Map<String, ?>但不匹配Map<String, Object> 。 假设你想写一个接受来自String的映射到任何东西的方法:如果你会写

 public void foobar(Map<String, Object> ms) { ... } 

你不能提供一个HashMap<String, String> 。 如果你写

 public void foobar(Map<String, ?> ms) { ... } 

有用!

Javagenerics中有时会被误解的是List<String>不是List<Object>的子types。 (但是String[]实际上是Object[]一个子types,这就是generics和数组混合不好的原因之一(Java中的数组是协变的,generics不是,它们是不变的 ))。

示例:如果您希望编写一个接受InputStreamInputStream子类的List的方法,您可以编写

 public void foobar(List<? extends InputStream> ms) { ... } 

顺便说一下,当你想了解Java中不那么简单的东西时, Joshua Bloch的Effective Java是一个很好的资源。 (你上面的问题在这本书中也有很好的介绍。)

另一种思考这个问题的方法是

 HashMap<String, ?> hash1; 

相当于

 HashMap<String, ? extends Object> hash1; 

将这些知识与Javagenerics和集合的 2.4节中的“获取和放置原则”相结合:

获取和放置原则:当您只将结构值从结构中取出时,使用扩展通配符;当只将值放入结构中时使用超级通配符;当两者都得到并放置时不使用通配符。

外卡可能会开始更有意义,希望。

如果您记得Collection<Object>只是一个包含ObjecttypesObject的generics集合,但Collection<?>是所有types集合的超types,则很容易理解。

你不能安全地把任何东西放到Map<String, ?> ,因为你不知道这个值应该是什么types。

您可以将任何对象放入Map<String, Object> ,因为该值已知为Object

协方差以上的答案涵盖大多数情况,但错过了一件事情:

“?” 包含类层次结构中的“对象”。 你可以说String是Object的一种,Object是一种types的。 并不是所有的东西都符合对象,但所有的东西都匹配?

 int test1(List<?> l) { return l.size(); } int test2(List<Object> l) { return l.size(); } List<?> l1 = Lists.newArrayList(); List<Object> l2 = Lists.newArrayList(); test1(l1); // compiles because any list will work test1(l2); // compiles because any list will work test2(l1); // fails because a ? might not be an Object test2(l2); // compiled because Object matches Object