理解Java中捕获的类型(symbol';?';)

理解Java中捕获的类型(symbol';?';),java,generics,Java,Generics,什么是?。它是否与Java编译器的实现细节有关,或者类型是在中定义的 比如说, public interface RecipientTypeVisitor<ReturnType> { public ReturnType visit(RecipientSetType t); } public class RecipientSetType extends RecipientType{ public Integer accept(RecipientTypeVisitor

什么是
。它是否与Java编译器的实现细节有关,或者类型是在中定义的

比如说,

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
    }
}
公共接口RecipientTypeVisitor{
公众返回型访问(接受者t型);
}
公共类RecipientSetType扩展了RecipientType{
公共整数接受(RecipientTypeVisitor){//错误:
return visitor.visit(this);//无法将#1的捕获转换为整数
}
}
但如果我们写这篇文章:

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.
    }
}
公共接口RecipientTypeVisitor{
公众返回型访问(接受者t型);
}
公共类RecipientSetType扩展了RecipientType{
公共对象接受(RecipientTypeVisitor){//Ok:
回访者。访问(此);//这意味着捕获#1是
//对象的子类型,如Java中的任何引用类型。
}
}

关于
捕获类型
,我只能说这些了。那么它到底是什么呢

每个类都从Object扩展,因此从
Object的类型转换是安全的。

要获得与
Integer
相同的结果,您可以使用
RecipientTypeVisitor您有一些选择:

  • 你必须更换吗?接受方法签名中的整数
  • 您也可以将您的方法参数化:
  • public不接受(RecipientTypeVisitor){…}


    这表示您的方法使用了一些泛型并链接了它的一些组件。

    通配符类型的捕获是编译器使用的一种类型,它在一个特定位置表示通配符类型的特定实例的类型

    示例:以具有两个通配符参数的方法为例,
    void m(exe1,exe2)
    e1
    e2
    的声明类型完全相同,
    Ex
    。但是
    e1
    e2
    可能具有不同且不兼容的运行时类型

    类型检查器即使以相同的方式编写也不能考虑类型相同。因此,在编译过程中,

    e1
    e2
    的类型参数被赋予了特定的类型,每个地方都使用了新的类型。这些新类型称为其声明类型的捕获

    通配符的捕获是一种未知的、正常的、具体的类型。它的使用方法与其他类型相同

    有关这方面的技术说明,请参见:

    5.1.10。捕获转换

    让G命名一个泛型类型声明(§8.1.2,§9.1.2),其中包含n个类型参数A1,…,An以及相应的边界U1,…,Un

    存在从参数化类型G(§4.5)到参数化类型G的捕获转换,其中,对于1≤ 我≤ n:

    • 如果Ti是形式为?的通配符类型参数(§4.5.1),则Si是一个新类型变量,其上限为Ui[A1:=S1,…,An:=Sn],下限为null类型(§4.1)
    我们可以将此应用于您的示例:

    public Integer accept(RecipientTypeVisitor<?> visitor){ //Error:
        return visitor.visit(this);             //Cannot convert capture of #1 to Integer
    }
    

    字符
    是一个通配符,表示您不知道类型。its并不意味着它的类型是
    对象
    its的定义
    未定义
    ,但在Java中,您可以在
    对象
    类型中保存任何类型的对象

    ArrayList<?> list1 = new Arraylist<?>(); // list of undefined objects
    
    ArrayList list1=new ArrayList();//未定义对象列表
    
    不能在列表1中添加对象,但在强制转换后可以

    ArrayList<Object> list2 = new Arraylist<Object>(); // list of objects of type Object
    
    ArrayList list2=新建ArrayList();//对象类型的对象列表
    
    您可以在列表2中添加任何类型的对象(这是我的另一个答案,但它更适合这个问题,解释通配符本身)

    通配符
    不是类型。这是一个类型参数。虽然语法很有欺骗性(故意)

    让我们使用不同的语法-如果有任何第一级通配符,请使用
    {}
    而不是
    ,例如

    List{?},  Map{String, ? extends Number}
    
    {?}
    的意思是声明联合类型

    List{? extends Number}  ==  union of List<Number>, List<Integer>, List<Long>, ....
    
    对于通配符,这是不可能做到的-它没有任何意义

        interface List<?>
            ? get(int)
    
    即使编译时不知道
    x
    的确切类型,我们仍然可以进行替换

        interface List<x>
            x get(int)
    
    接口列表
    x获取(int)
    

    所以我们可以理解调用obj.get(0)
    ;它返回
    x
    ,并且
    x
    对象的子类型;因此,我们可以将返回值分配给
    对象

    ,您想知道有关此对象的确切信息吗?好像是班名?或者别的什么?你想知道为什么你的第一个例子没有编译吗
    visitor.visit()
    返回一个
    ReturnType
    ,它不能作为
    整数返回,而是作为
    对象返回。在RecipientTypeVisitor中,“?”是一个通配符,您不知道它的类型。如何假定它的整数?所以对于它的编译器来说Object@Aakash我想知道我到底问了些什么。是JLS中定义的类型(及其属性),或者只是实现的内部构件。它可以是
    ReturnType
    或它的子类之一。上面的示例也可以在Maurice Naftalin&Philip Wadler的《Java泛型和集合通配符捕获》一书中找到。类型变量T已捕获通配符
        interface List<?>
            ? get(int)
    
    obj is a List{?}  =>  obj is a List<x>, where x a subtype of Object.
    
        interface List<x>
            x get(int)