Pra*_*mar 11 java generics diamond-operator java-7
给出了泛型教程中的这个例子.
List<String> list = new ArrayList<>();
list.add("A");
// The following statement should fail since addAll expects
// Collection<? extends String>
list.addAll(new ArrayList<>());
Run Code Online (Sandbox Code Playgroud)
为什么最后一行不能编译,它似乎应该编译.第一行使用非常相似的构造并编译没有问题.
请详细解释.
Joa*_*uer 14
首先:除非您使用的是Java 7,否则所有这些都不起作用,因为仅在该Java版本中引入了钻石<>.
此外,这个答案假定读者理解泛型的基础知识.如果不这样做,请阅读本教程的其他部分,并在理解这些部分后再回来.
当编译器可以自己找出类型时,菱形实际上是不必重复泛型类型信息的快捷方式.
最常见的用例是当变量在其初始化的同一行中定义时:
List<String> list = new ArrayList<>(); // is a shortcut for
List<String> list = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)
在这个例子中,差异并不重要,但一旦你达到Map<String, ThreadLocal<Collection<Map<String,String>>>>它将是一个重大的增强(注意:我不鼓励实际使用这样的结构!).
问题是规则只走了那么远.在上面的例子中,很明显应该使用什么类型,编译器和开发人员都同意.
在这一行:
list.addAll(new ArrayList<>());
Run Code Online (Sandbox Code Playgroud)
这似乎是显而易见的.至少开发人员知道类型应该是String.
但是,看一下Collection.addAll()我们看到参数类型的定义Collection<? extends E>.
这意味着addAll接受任何包含任何未知类型的对象的集合,这些对象扩展了我们的类型list.这很好,因为它意味着你可以addAlla List<Integer>到a List<Number>,但它使我们的类型推理更棘手.
实际上,它使类型推断不适用于JLS当前规定的规则.在某些情况下,可以认为规则可以扩展到工作,但目前的规则意味着不这样做.
类型推断文档中的解释似乎直接回答了这个问题(除非我遗漏了其他内容)。
Java SE 7 及更高版本支持通用实例创建的有限类型推断;仅当构造函数的参数化类型从上下文中显而易见时,才可以使用类型推断。例如,以下示例无法编译:
List<String> list = new ArrayList<>();
list.add("A");
// The following statement should fail since addAll expects
// Collection<? extends String>
list.addAll(new ArrayList<>());
Run Code Online (Sandbox Code Playgroud)
请注意,菱形通常在方法调用中起作用;然而,为了更清楚起见,建议您主要使用菱形来初始化声明变量的地方。
相比之下,以下示例可以编译:
// The following statements compile:
List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12545 次 |
| 最近记录: |