Java 10 var 和捕获变量

Java 10 var and capture variable

我正在阅读 JEP 286 但我不明白这部分:

Capture variables, and types with nested capture variables, are projected to supertypes that do not mention capture variables. This mapping replaces capture variables with their upper bounds and replaces type arguments mentioning capture variables with bounded wildcards (and then recurs). This preserves the traditionally limited scope of capture variables, which are only considered within a single statement.

任何人都可以在 Java 代码中给我一个具体的例子来说明它的含义吗?

var 允许您推断不可表示的类型:

var x = new Object() {
    int i = 10;
};

System.out.println(x.i); // works; `x` has the non-denotable type of the annonymous class

所以从理论上讲,这将允许您推断通配符类型。但是这篇文章的意思是那是不可能的,因为通配符被它的上限所取代,或者被推断类型中的新捕获变量所取代。

以这段代码为例:

List<String> l1 = new ArrayList<>();
l1.add("Hello");
List<?> l2 = l1;

var x = l2.get(0);
l2.add(x); // error

在这里,而不是 x 的类型被推断为通配符的确切类型,这将使​​最后一行编译。相反,它被推断为它的上限,即 Object,您会收到 (Eclipse) 错误消息:

The method add(capture#2-of ?) in the type List<capture#2-of ?> is not applicable for the arguments (Object)

哪里可以看到x的类型是Object.

这就是部分

This mapping replaces capture variables with their upper bounds


第二部分

... and replaces type arguments mentioning capture variables with bounded wildcards

说的是这样的情况:

List<String> l1 = new ArrayList<>();
l1.add("Hello");
List<?> l2 = l1;
var l3 = l2; // type of 'l3' is List<?>, but not the same '?' as 'l2'

l3.add(l2.get(0)); // error

这也不编译,因为 l3 的类型与 l2 的类型不完全相同,这意味着从 l2.get(0) 返回的类型是与 l3.add(...) 要求的类型不同。这里的错误是:

The method add(capture#2-of ?) in the type List<capture#2-of ?> is not applicable for the arguments (capture#3-of ?)

并且你看到两个捕获变量是不同的,这意味着l3的类型不完全是l2的类型,而是[=21]类型的捕获变量=] 在推断类型中被替换为具有相同边界的通配符,然后为其创建一个新的捕获变量。

因此对于类型 List<capture#1-of ?>,推断类型为 List<?>,然后编译器为该通配符创建一个新的捕获变量,产生 List<capture#2-of ?>(尽管编号可能有不同的工作方式实际上,关键是2个捕获变量不同。