[英]Why does the List<? extends Foo> not accept an object of the Foo class?
[英]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
或之间的某个其它祖先类Object
和Pair<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的规则仅适用于wildcardsMethod
的list
引用,而不适用于listOfPairOfObjects
引用。
因此我可以
Pair<Object> pairOfObjects = listOfPairOfObjects.get(0);
现在,由于将Pair<Number>
添加到该方法的列表中,因此当我希望使用Pair<Object>
引用时 , 我将收到Pair<Number>
对象 。
这些都是完全不兼容的类型。 因此,错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.