为什么钻石操作员不在Java 7的addAll()调用中工作? [英] Why doesn't the diamond operator work within a addAll() call in Java 7?

查看:154

首先:除非你使用Java 7,否则所有这些都不起作用,因为菱形<> 仅在该Java版本中引入。



此外,这个答案假定读者了解泛型的基础知识。如果你不这样做,那么阅读本教程的其他部分 ,当你理解它们时回来。

钻石实际上是一条捷径因为当编译器可以自行找出类型时,不必重复泛型类型信息。

最常见的用例是当变量定义在同一个它已初始化:

  List< String> list = new ArrayList<>(); //是
的快捷方式List< String> list = new ArrayList< String>();

在这个例子中差异不是很大,但是一旦你得到 Map< String,ThreadLocal< Collection< Map< String,String>>>>>< / code>它将成为主要



问题在于规则只有那么多。在上面的例子中,很明显应该使用哪种类型,并且编译器和开发人员都同意。



在这一行上:

  list.addAll(new ArrayList<>)); 

似乎显而易见。至少开发人员知道该类型应该是 String

然而,看看 Collection.addAll() 我们看到参数类型为 Collection <?这意味着 addAll 接受任何包含以下对象的集合:> E>

任何未知类型扩展了我们的列表的类型。这很好,因为这意味着您可以将 addAll a List< Integer> 添加到 List< Number> ; ,但它使我们的类型推断更加棘手。



事实上,它使类型推断不能在目前由JLS。在一些情况下,可能会认为规则可以扩展到工作状态,但目前的规则意味着不这样做。

Given this example from the generics tutorial.

List<String> list = new ArrayList<>();
list.add("A");

// The following statement should fail since addAll expects
// Collection<? extends String>

list.addAll(new ArrayList<>());

Why does the last line not compile, when it seems it should compile. The first line uses a very similar construct and compiles without a problem.

Please explain elaborately.

解决方案

First of all: unless you're using Java 7 all of this will not work, because the diamond <> has only been introduced in that Java version.

Also, this answer assumes that the reader understands the basics of generics. If you don't, then read the other parts of the tutorial and come back when you understand those.

The diamond is actually a shortcut for not having to repeat the generic type information when the compiler could find out the type on its own.

The most common use case is when a variable is defined in the same line it's initialized:

List<String> list = new ArrayList<>(); // is a shortcut for
List<String> list = new ArrayList<String>();

In this example the difference isn't major, but once you get to Map<String, ThreadLocal<Collection<Map<String,String>>>> it'll be a major enhancement (note: I don't encourage actually using such constructs!).

The problem is that the rules only go that far. In the example above it's pretty obvious what type should be used and both the compiler and the developer agree.

On this line:

list.addAll(new ArrayList<>());

it seems to be obvious. At least the developer knows that the type should be String.

However, looking at the definition of Collection.addAll() we see the parameter type to be Collection<? extends E>.

It means that addAll accepts any collection that contains objects of any unknown type that extends the type of our list. That's good because it means you can addAll a List<Integer> to a List<Number>, but it makes our type inference trickier.

In fact it makes the type-inference not work within the rules currently laid out by the JLS. In some situations it could be argued that the rules could be extended to work, but the current rules imply don't do it.

这篇关于为什么钻石操作员不在Java 7的addAll()调用中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆