我正在努力解决捕获的转换如何适用于通配符类型。 JLS中有一节解释:
让
G
使用n
类型参数A1,...,An
命名通用类型声明(第8.1.2节,第9.1.2节),并使用相应的边界U1,...,Un
。存在来自参数化类型的捕获转换
G<T1,...,Tn>
(§4.5)到参数化类型G<S1,...,Sn>
,其中,1 ≤ i ≤ n
:
如果
Ti
是?
形式的通配符类型参数(第4.5.1节),则Si
是 新的类型变量,其上限为Ui[A1:=S1,...,An:=Sn]
和 其下限是null
类型(§4.1)。如果
Ti
是? extends Bi
形式的通配符类型参数,那么Si
是 一个新的类型变量,其上限为glb(Bi, Ui[A1:=S1,...,An:=Sn])
,其下限为null
类型。
glb(V1,...,Vm)
定义为V1 & ... & Vm
。对于任何两个类(不是接口)
Vi
,如果是编译时错误Vj
,Vi
不是Vj
的子类,反之亦然。如果
Ti
是? super Bi
形式的通配符类型参数,则Si
是 新的类型变量,其上限为Ui[A1:=S1,...,An:=Sn]
和 其下限为Bi
。否则,
Si = Ti
。
我不清楚的是Ui[A1:=S1,...,An:=Sn]
。这是什么意思?我无法找到通过JLS搜索的定义。
答案 0 :(得分:4)
首先:定义替换。
[A1:=S1,...,An:=Sn]
是substitution in JLS notation (§1.3),定义为:
符号
[F1:=T1,...,Fn:=Tn]
表示将Fi
替换为Ti
1 ≤ i ≤ n
。
声明:[A1:=S1,...,An:=Sn]
是参数(G
)Ai
类型替换类型变量 {{ 1}} Si
。 (另见脚注†)
下一步:考虑为什么在第一种情况下我们可能需要替换。从§5.1.10开始(突出显示添加到下一点开车回家):
让
1 ≤ i ≤ n
为通用类型声明命名...G
类型参数n
,带有相应的边界A1,...,An
。
那是:
U1,...,Un
专门针对类型参数U1,...,Un
。A1,...,An
与类型变量U1,...,Un
不对应。把它放在一起:我现在正在说明这一点,因为我确信你领先于我,但是...
关于“ S1,...,Sn
的规则是Ti
形式的通配符类型参数...”
?
是一个新的类型变量,其上限为Si
Ui [A1:=S1,...,An:=Sn]
是一个新类型变量Si
Ui
,A1,...,An
专门与U1,...,Un
S1,...,Sn
对应于类型变量U1,...,Un
即。它只是意味着原始上限S1,...,Sn
也是Ui
†回忆一下from the JLS类型变量和类型参数不是一回事就很有帮助(因此我们可以开始明白为什么需要替换):
类型变量是一个非限定标识符,用作类,接口,方法中的类型, 和构造函数体。
类型变量由泛型类,接口,方法或构造函数的类型参数的声明引入。
答案 1 :(得分:1)
这意味着&#34;替代&#34;具有实际类型的类型变量。例如
List<T>[T:=String] => List<String>
Enum<E extends Enum<E>>
A1=E
U1=Enum<E>
Enum<?> capture convertion to Enum<S1>
U1[A1:=S1] => Enum<S1>
S1's upper bound is Enum<S1>
语法可能来自lambda calculus