问题
我正在使用Eclipse来帮助我清理一些代码以正确使用Java泛型。大多数情况下,它在推断类型方面做得非常出色,但在某些情况下,推断类型必须尽可能通用:对象。但Eclipse似乎给了我一种选择在一种Object和一种'?'之间的选择。
那么有什么区别:
HashMap<String, ?> hash1;
和
HashMap<String, Object> hash2;
#1 热门回答(112 赞)
一个实例HashMap<String, String>
匹配Map<String, ?>
但不是Map<String, Object>
。假设你要编写一个接受从String
到任何 Map 的方法:如果你愿意写
public void foobar(Map<String, Object> ms) {
...
}
你不能提供aHashMap<String, String>
。如果你写
public void foobar(Map<String, ?> ms) {
...
}
有用!
在Java的泛型中有时会被误解的是List<String>
不是List<Object>
的子类型。 (但是String[]
实际上是Object[]
的子类型,这是泛型和数组不能很好混合的原因之一。(Java中的数组是协变的,泛型不是,它们是不变的))。
示例:如果你想编写一个接受List
s的InputStream
s和子类型为InputStream
的方法,那么你就写了
public void foobar(List<? extends InputStream> ms) {
...
}
顺便说一句:Joshua Bloch's Effective Java是一个很好的资源,当你想要了解Java中不那么简单的东西时。 (上面的问题在本书中也有很好的介绍。)
#2 热门回答(27 赞)
另一种思考这个问题的方法是
HashMap<String, ?> hash1;
相当于
HashMap<String, ? extends Object> hash1;
将这些知识与Java Generics and Collections节(2.4)中的"获取和放置原则"结合起来:
获取和放置原则:当你只从结构中获取值时使用扩展通配符,当你仅将值放入结构时使用超级通配符,并且当你同时获取和放置时不使用通配符。
希望,外卡可能会开始变得更有意义。
#3 热门回答(8 赞)
如果你记得Collection<Object>
只是一个包含typeObject
对象的泛型集合,那么很容易理解,但是Collection<?>
是所有类型集合的超类型。