我正在使用Eclipse来帮助我清理一些代码以正确使用Java泛型.大多数情况下,它在推断类型方面做得非常出色,但在某些情况下,推断类型必须尽可能通用:对象.但Eclipse似乎给了我一种选择在一种Object和一种'?'之间的选择.
那么有什么区别:
HashMap<String, ?> hash1;
Run Code Online (Sandbox Code Playgroud)
和
HashMap<String, Object> hash2;
Run Code Online (Sandbox Code Playgroud)
Joh*_*iss 135
HashMap<String, String>匹配的实例Map<String, ?>但不是Map<String, Object>.假设你想编写一个接受从Strings到任何东西的地图的方法:如果你愿意的话
public void foobar(Map<String, Object> ms) {
...
}
Run Code Online (Sandbox Code Playgroud)
你不能提供HashMap<String, String>.如果你写
public void foobar(Map<String, ?> ms) {
...
}
Run Code Online (Sandbox Code Playgroud)
有用!
在Java的泛型中有时会被误解的一点是,List<String>它不是一个子类型List<Object>.(但String[]实际上是一个子类型Object[],这是泛型和数组混合不好的原因之一.(Java中的数组是协变的,泛型不是,它们是不变的)).
示例:如果您想编写一个接受法List第InputStreamS和亚型InputStream,你会写
public void foobar(List<? extends InputStream> ms) {
...
}
Run Code Online (Sandbox Code Playgroud)
顺便说一下:当你想要理解Java中不那么简单的东西时,Joshua Bloch的Effective Java是一个很好的资源.(上面的问题在本书中也很清楚.)
Jul*_*ang 32
另一种思考这个问题的方法是
HashMap<String, ?> hash1;
Run Code Online (Sandbox Code Playgroud)
相当于
HashMap<String, ? extends Object> hash1;
Run Code Online (Sandbox Code Playgroud)
将这些知识与Java Generics and Collections的第(2.4)节中的"获取和放置原则"结合起来:
获取和放置原则:当您只从结构中获取值时使用扩展通配符,当您仅将值放入结构时使用超级通配符,并且当您同时获取和放置时不使用通配符.
希望,外卡可能会开始变得更有意义.
以上协方差的答案涵盖了大多数情况,但遗漏了一件事:
“?” 包括类层次结构中的“对象”。你可以说 String 是 Object 的类型,Object 是 ? 的类型。并非所有内容都匹配 Object,但所有内容都匹配 ?。
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30404 次 |
| 最近记录: |