Java 10 var和捕获变量

时间:2018-08-01 10:19:54

标签: java java-10

我正在阅读JEP 286,但我听不懂这部分内容:

  

捕获变量和具有嵌套捕获变量的类型是   投射到不提及捕获变量的超类型。这个   映射将捕获变量替换为其上限,并且   用有界替换替换提及捕获变量的类型参数   通配符(然后重复出现)。这保留了传统上有限的   捕获变量的范围,仅在单个变量内考虑   声明。

有人可以在Java代码中为我具体说明一个例子吗?

1 个答案:

答案 0 :(得分:15)

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

那是一部分

  

此映射将捕获变量替换为其上限


第二部分

  

...并用有界通配符替换提及捕获变量的类型参数

正在谈论这样的情况:

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的类型,而是l2类型的捕获变量推断类型中的替换为具有相同界限的通配符,然后为其创建新的捕获变量。

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