问题

我正在使用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中的数组是协变的,泛型不是,它们是不变的))。

示例:如果你想编写一个接受Lists的InputStreams和子类型为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<?>是所有类型集合的超类型。


原文链接