类型变量和参数的定义

我正在使用Java语言规范第三版阅读Java中的generics。 在“ 4.6擦除 ”部分中,定义了擦除类型。 关于类型变量的擦除,它说

类型变量(第4.4节)的擦除是其最左边界的擦除。

这让我对类型变量类型参数之间的区别感到困惑,因为“ 4.4类型变量 ”部分具有以下定义: TypeParameter: TypeVariable TypeBound ,其中bound是可选的。 但也许您可以使用它出现的类型参数来识别类型变量,因为类型变量只能(?)出现在一个“上下文”中,然后类型变量的最左边界限被定义为其对应的类型参数或Object的最左边界限如果类型参数中没有显式绑定?

如果没有为类型变量给出绑定,则假定为Object。

在您的链接中找到。 这意味着给定FirstClassSecondClass你会得到:

  1. 类: FirstClass类型参数: T extends String 。 类型变量: T 。 键入Bound: String
  2. 类: SecondClass类型参数: V类型变量: V 。 类型绑定:默认为Object

编辑:类型参数类型变量类型绑定我不是指语法规则,而是概念。 因此, extends只是关键字。

关于最左边的边界,你可以在同一个链接中找到答案,第一个引用后的两个句子:

绑定中类型的顺序只是重要的,因为类型变量的擦除由其边界中的第一个类型确定,并且类类型或类型变量可能仅出现在第一个位置。

TL; DR上下文就是一切!


非正式地,“ 类型变量 ”和“ 类型参数 ”可互换使用,作为彼此的同义词[ 甚至是Gilad Bracha– Java的generics实现的创建者 ]。

然而,forms上, JLS明确地将它们描述为两种不同但又密切相关的抽象。

在过去,我自己也有类似的问题,关于generics的许多文献中关于“ 类型参数 ”和“ 类型变量 ”这两个术语的使用不那么明确。

根据我对更新的Java 8 JLS的解释TypeParameter出现在参数化类’或方法的类型参数部分[ 声明的<>部分 ]中。

JLS说,“ 类型变量是由类型参数的声明引入的 ……” 。 我将其解释为,为了使用TypeVariable ,您必须首先按照为声明TypeParameter指定的规则填写方法的[ 或类’ ]类型参数部分…

 TypeParameter: {TypeParameterModifier} Identifier [TypeBound] TypeParameterModifier: Annotation TypeBound: extends TypeVariable extends ClassOrInterfaceType {AdditionalBound} AdditionalBound: & InterfaceType 

阅读TypeParameter的上述语法生成,以及TypeVariable这个

 TypeVariable: {Annotation} Identifier 

…我将这两个产品解释为如果标识符TT具有[ 或可能具有 ] TypeBound的上下文中使用,那么TTypeParameter 。 或者,如果在不允许TypeBound上下文中使用标识符T ,则TTypeVariable


我认为TypeParameter类似于方法声明的forms参数

JLS说“ 一个类型变量是一个在类,接口,方法和构造函数体中用作类型的非限定标识符 ”时 ,我将其解释为在类型参数部分中声明一个TypeParameter ,也类似于在某种意义上 ,声明一个类可以随后用作实例变量的引用类型。

我的意思是,为了让以下内容合法……

 class Foo { private Bar bar; } class Boff extends Foo { } 

..然后你必须首先介绍 Bar类型的声明,然后才能在Foo的主体中使用它。 类似地,必须首先声明类型参数 ,以使以下内容合法……

 class Baz { /* The TypeParameter that "introduces" T comes first */ private T quux; /* now T is a TypeVariable in this context */ /*  is the TypeParameter that "introduces" the TypeVariable, U */ public  List m( Class clazz ) throws Exception { /*  is the TypeParameter */ U u = clazz.newInstance( ); /* U is a TypeVariable in this context */ /*...*/ List list = new LinkedList<>(); /* U is a TypeVariable in this context; just like it is in this method's return type */ /*...*/ list.add( u ); /*...*/ return list; } } 

如果我被允许更具体……

 Baz buzz = new Baz<>(); 

<>菱形内的Boff既不是类型变量也不是类型参数 。 这是一个类型参数