我正在阅读JEP 286,但我听不懂这部分内容:
捕获变量和具有嵌套捕获变量的类型是 投射到不提及捕获变量的超类型。这个 映射将捕获变量替换为其上限,并且 用有界替换替换提及捕获变量的类型参数 通配符(然后重复出现)。这保留了传统上有限的 捕获变量的范围,仅在单个变量内考虑 声明。
有人可以在Java代码中为我具体说明一个例子吗?
答案 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 ?>
(尽管实际上编号可能会有所不同,关键是两个捕获变量不同)。