了解捕获的转化

时间:2015-07-03 12:31:02

标签: java generics

我正在努力解决捕获的转换如何适用于通配符类型。 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,如果是编译时错误   VjVi不是Vj的子类,反之亦然。

  •   
  • 如果Ti? super Bi形式的通配符类型参数,则Si是   新的类型变量,其上限为 Ui[A1:=S1,...,An:=Sn] 和   其下限为Bi

  •   
  • 否则,Si = Ti

  •   

我不清楚的是Ui[A1:=S1,...,An:=Sn]。这是什么意思?我无法找到通过JLS搜索的定义。

2 个答案:

答案 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]参数GAi类型替换类型变量 {{ 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
  • 其中(这是隐含位)
  • 类型参数UiA1,...,An专门与
  • 对应
  • 已替换类型变量U1,...,Un
  • 使S1,...,Sn对应于类型变量U1,...,Un

TL; DR

即。它只是意味着原始上限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