繁体   English   中英

为什么是富 <String> 被视为Foo的子类型(扩展) <? extends Object> ?

[英]Why is Foo<String> considered a subtype (extended) of Foo<? extends Object>?

这是此SO答案的扩展。

注意:这不是以下内容的重复项。 为什么List不是List<Number>的子类型,而是List<Number>子类型List<? extends Number> List<? extends Number> ,也不会将此问题标记为重复的任何问题。 让我解释。

实际的问题是 (已编辑以删除不必要的代码),

void wildcardsMethod(List<? super Pair<? super Number>> list) {}

//... From some method.
    List<Pair<Object>> list = null;
    wildcardsMethod(list);
    // Error: wildcardsMethod(List<? super Pair<? super Number>>) is not applicable for the arguments (List<Pair<Object>>)

以上无效

给出的答案类似于 (如果我没有误解的话),

Pair<Object>Pair<? super Number>子类型 Pair<? super Number> Pair<? super Number> ,因此不能代替<? super Pair<>> <? super Pair<>>

在这种情况下,我不理解。 我以为这只是一个Pair对象,我们应该可以代替两个<? extends Pair<>> <? extends Pair<>><? super Pair<>> <? super Pair<>> 但这在后者中不起作用。

有人可以解释为什么将其视为子类型,从而将其限制为仅extends而不是super

编辑:

为了进一步说明,让我们看看为什么要使用该方法(考虑PECS ),

void wildcardsMethod(List<? super Pair<? super Number>> list) {}

您将使用它来 Pair<Number>对象添加到传递的list

在这种情况下, List<Pair<Object>>是可以接受Pair<Number>对象的有效列表。

那么,为什么不允许这样做?

您可能缺少树木的森林,并认为List<Pair<Object>>List<? super Pair<? super Number>>相同List<? super Pair<? super Number>> List<? super Pair<? super Number>> List<? super Pair<? super Number>> ,如果不是

List<? super Pair<? super Object>> List<? super Pair<? super Object>>声明一个列表将包含任一Pair<Object>或的超类型 Pair<Object> ,它可以是Object或之间的某个其它祖先类ObjectPair<T> List<Pair<Object>>声明 Pair物体或可被视为一个对象Pair将在类曾经存在。

界限朝着不同的方向发展。 您隐式获得List<? extends Pair<? super Object>> List<? extends Pair<? super Object>> 带有第一个声明的List<? extends Pair<? super Object>>

合理执行此操作的唯一方法是,如果传入的列表也以类似的方式绑定。 也就是说,您希望传递一个List<? super Pair<? super Number>> List<? super Pair<? super Number>> List<? super Pair<? super Number>>

当您说“ A是B的子类型”时, 根据定义 ,这意味着A类型的每个对象也是B类型的对象。现在,如果用Foo<? extends Object> x;声明一个变量Foo<? extends Object> x; Foo<? extends Object> x; ,这意味着x可以引用的对象恰好是Foo<something>类型(其中something Object扩展了Object )的那些Object 显然,这包括类型为Foo<String>对象。

那么每个Foo<String>也是Foo<? extends Object> Foo<? extends Object> -因此根据定义, Foo<String>Foo<? extends Object>的子类型Foo<? extends Object> Foo<? extends Object>

同样,每个Pair<Object>也是Pair<? super Number> Pair<? super Number> -因此根据定义, Pair<Object>Pair<? super Number>的子类型Pair<? super Number> Pair<? super Number>

在思考了Makoto的答案一段时间后,我明白了它的含义。

注意:我以易于理解的格式编写此答案,以备将来参考(尽管他将被接受)

假设我们有这样定义的方法(考虑PECS),

void wildcardsMethod(List<? super Pair<? super Number>> list) {
    Pair<Number> pairOfNumbers = new Pair<Number>();
    list.add(pairOfNumbers);
}

并且我们使用此参数调用该方法( 假设已允许 ),

List<Pair<Object>> listOfPairOfObjects = new ArrayList<Pair<Object>>();
wildcardsMethod(listOfPairOfObject);

现在,将Pair<Number>对象添加到listOfPairOfObjects

还要记住, PECS的规则仅适用wildcardsMethodlist引用,而不适用于listOfPairOfObjects引用。

因此我可以

Pair<Object> pairOfObjects = listOfPairOfObjects.get(0);

现在,由于将Pair<Number>添加到该方法的列表中,因此当我希望使用Pair<Object>引用时我将收到Pair<Number>对象

这些都是完全不兼容的类型。 因此,错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM