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

ski*_*ppy 128 java generics

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

示例:如果您想编写一个接受法ListInputStreamS和亚型InputStream,你会写

public void foobar(List<? extends InputStream> ms) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

顺便说一下:当你想要理解Java中不那么简单的东西时,Joshua Bloch的Effective Java是一个很好的资源.(上面的问题在本书中也很清楚.)

  • Object 是所有 Java 类的超类型,但是,Object 的集合不是任何集合的超类型。例如,List&lt;Object&gt; 不是 List&lt;String&gt; 的超类型,将 List&lt;Object&gt; 类型的变量分配给 List&lt;String&gt; 类型的变量将导致编译器错误。 (3认同)
  • 这是在控制器级别为我的所有控制器功能使用 ResponseEntity&lt;?&gt; 的正确方法吗? (2认同)

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)节中的"获取和放置原则"结合起来:

获取和放置原则:当您只从结构中获取值时使用扩展通配符,当您仅将值放入结构时使用超级通配符,并且当您同时获取和放置时不使用通配符.

希望,外卡可能会开始变得更有意义.

  • 感谢您提供更多信息.我还在消化它.:) (2认同)

top*_*hef 11

如果你记得它Collection<Object>只是一个包含类型对象的泛型集合Object,但它Collection<?>是所有类型集合的超类型,这很容易理解.


Eya*_*yal 6

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

“?” 包括类层次结构中的“对象”。你可以说 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)