了解Java中的捕获类型(符号'?')
什么是?
。它与Java编译器的实现细节有关还是JLS中定义的类型有关?
例如,
public interface RecipientTypeVisitor<ReturnType> { public ReturnType visit(RecipientSetType t);
}
public class RecipientSetType extends RecipientType{
public Integer accept(RecipientTypeVisitor<?> visitor){ //Error:
return visitor.visit(this); //Cannot convert capture of #1 to Integer
}
}
但是,如果我们这样写:
public interface RecipientTypeVisitor<ReturnType> { public ReturnType visit(RecipientSetType t);
}
public class RecipientSetType extends RecipientType{
public Object accept(RecipientTypeVisitor<?> visitor){ //Ok:
return visitor.visit(this); //this implies tha the capture of #1 is
//a subtype of Object as any refrence type in Java.
}
}
这就是我能说的captured type
。那到底是什么呢?
回答:
捕获通配符类型是编译器使用的一种类型,它在一个特定位置代表通配符类型的特定实例的类型。
示例:以具有两个通配符参数的方法为例void m(Ex<?> e1, Ex<?>
e2)。声明的类型e1
和e2
被写入完全相同,Ex<?>
。但是e1
和e2
可能具有不同且不兼容的运行时类型。
即使以相同的方式编写类型,类型检查器也不能认为类型相等。因此,在编译期间,e1
和的类型参数将e2
被赋予特定的类型,并在每个使用它们的地方使用新的类型。这些新类型称为其声明类型的
捕获 。
捕获通配符是未知的,但是是普通的和具体的类型。可以与其他类型相同的方式使用。
可以在JLS中找到对此的技术描述:
5.1.10。捕获转化
让G命名具有n个类型参数A1,…,An并具有相应范围U1,…,Un的通用类型声明(第8.1.2节,第9.1.2节)。
存在从参数化类型G(第4.5节)到参数化类型G的捕获转换,其中对于1≤i≤n:
- 如果Ti是形式为?的通配符类型参数(第4.5.1节),则Si是新鲜类型变量,其上限为Ui [A1:= S1,…,An:=
Sn],下限为空类型(第4.1节)。
- …
我们可以将其应用于您的示例:
public Integer accept(RecipientTypeVisitor<?> visitor){ //Error: return visitor.visit(this); //Cannot convert capture of #1 to Integer
}
RecipientTypeVisitor
在编译期间引入了对type参数的捕获。捕获的类型参数是具体的,但完全未知(JLS将此称为“新类型变量”),并且肯定不能转换为Integer
。
无法直接表示捕获通配符类型,因此您不能声明该类型的变量或对其进行过多处理。但是,您可以通过以其为参数调用泛型方法来间接获得其名称。我引用的JLS部分对此有一个很好的示例:
public static void reverse(List<?> list) { rev(list); }
private static <T> void rev(List<T> list) {
List<T> tmp = new ArrayList<T>(list);
for (int i = 0; i < list.size(); i++) {
list.set(i, tmp.get(list.size() - i - 1));
}
}
以上是 了解Java中的捕获类型(符号'?') 的全部内容, 来源链接: utcz.com/qa/414299.html