[英]Why is Foo<String> considered a subtype (extended) of Foo<? extends Object>?
This is an extension of this SO answer . 这是此SO答案的扩展。
Note: This is not a duplicate of the following. 注意:这不是以下内容的重复项。 Why List is not a subtype of
List<Number>
but is subtype ofList<? extends Number>
为什么List不是List<Number>
的子类型,而是List<Number>
子类型List<? extends Number>
List<? extends Number>
?List<? extends Number>
? , nor any of the questions this has been marked duplicate of. ,也不会将此问题标记为重复的任何问题。 Let me explain. 让我解释。
The actual question was (edited to remove unnecessary code), 实际的问题是 (已编辑以删除不必要的代码),
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>>)
The above doesn't work . 以上无效 。
And the answer given was similar to (if I have not misunderstood), 给出的答案类似于 (如果我没有误解的话),
Pair<Object>
is a subtype ofPair<? super Number>
Pair<Object>
是Pair<? super Number>
的子类型Pair<? super Number>
Pair<? super Number>
and so it cannot be used in place of<? super Pair<>>
Pair<? super Number>
,因此不能代替<? super Pair<>>
<? super Pair<>>
.<? super Pair<>>
。
I don't understand it in this context. 在这种情况下,我不理解。 I was thinking it's just a Pair
object and we should be able to use it in place of both <? extends Pair<>>
我以为这只是一个Pair
对象,我们应该可以代替两个<? extends Pair<>>
<? extends Pair<>>
and <? super Pair<>>
<? extends Pair<>>
和<? super Pair<>>
<? super Pair<>>
. <? super Pair<>>
。 But it doesn't work in the latter. 但这在后者中不起作用。
Can someone explain why it's considered to be a subtype thus limiting it to only extends
and not super
. 有人可以解释为什么将其视为子类型,从而将其限制为仅extends
而不是super
。
To explain a little more, let's see why we will the method (considering PECS ), 为了进一步说明,让我们看看为什么要使用该方法(考虑PECS ),
void wildcardsMethod(List<? super Pair<? super Number>> list) {}
You will be using it to add a Pair<Number>
object to the passed list
. 您将使用它来将 Pair<Number>
对象添加到传递的list
。
In this case, List<Pair<Object>>
is a valid list which can accept a Pair<Number>
object. 在这种情况下, List<Pair<Object>>
是可以接受Pair<Number>
对象的有效列表。
So, why is this not allowed? 那么,为什么不允许这样做?
You might be missing the forest for the trees, and think that List<Pair<Object>>
is the same as List<? super Pair<? super Number>>
您可能缺少树木的森林,并认为List<Pair<Object>>
与List<? super Pair<? super Number>>
相同List<? super Pair<? super Number>>
List<? super Pair<? super Number>>
List<? super Pair<? super Number>>
, when they are not . List<? super Pair<? super Number>>
,如果不是 。
List<? super Pair<? super Object>>
List<? super Pair<? super Object>>
declares that a list will contain either Pair<Object>
or a supertype of Pair<Object>
, which could be Object
or some other ancestral class between Object
and Pair<T>
. List<? super Pair<? super Object>>
声明一个列表将包含任一Pair<Object>
或的超类型 Pair<Object>
,它可以是Object
或之间的某个其它祖先类Object
和Pair<T>
List<Pair<Object>>
declares that only Pair
objects or objects that can be considered a Pair
will ever exist in that class. List<Pair<Object>>
声明只 Pair
物体或可被视为一个对象Pair
将在类曾经存在。
The bounds are going in different directions. 界限朝着不同的方向发展。 You're implicitly getting List<? extends Pair<? super Object>>
您隐式获得List<? extends Pair<? super Object>>
List<? extends Pair<? super Object>>
List<? extends Pair<? super Object>>
with the first declaration. 带有第一个声明的List<? extends Pair<? super Object>>
。
The only way you could reasonably do this is if the list you were passing in were also bound in a similar fashion. 合理执行此操作的唯一方法是,如果传入的列表也以类似的方式绑定。 That is, you would want to be passing in a List<? super Pair<? super Number>>
也就是说,您希望传递一个List<? super Pair<? super Number>>
List<? super Pair<? super Number>>
List<? super Pair<? super Number>>
. List<? super Pair<? super Number>>
。
When you say "A is a subtype of B", what that means by definition , is that every object of type A is also an object of type B. Now if you declare a variable with Foo<? extends Object> x;
当您说“ A是B的子类型”时, 根据定义 ,这意味着A类型的每个对象也是B类型的对象。现在,如果用Foo<? extends Object> x;
声明一个变量Foo<? extends Object> x;
Foo<? extends Object> x;
, that means that the objects that x
can refer to are precisely those objects which are of type Foo<something>
(where something
extends Object
). ,这意味着x
可以引用的对象恰好是Foo<something>
类型(其中something
Object
扩展了Object
)的那些Object
。 Obviously, that includes objects of type Foo<String>
. 显然,这包括类型为Foo<String>
对象。
So every Foo<String>
is also a Foo<? extends Object>
那么每个Foo<String>
也是Foo<? extends Object>
Foo<? extends Object>
- so by definition, Foo<String>
is a subtype of Foo<? extends Object>
Foo<? extends Object>
-因此根据定义, Foo<String>
是Foo<? extends Object>
的子类型Foo<? extends Object>
Foo<? extends Object>
. Foo<? extends Object>
。
Likewise, every Pair<Object>
is also a Pair<? super Number>
同样,每个Pair<Object>
也是Pair<? super Number>
Pair<? super Number>
- so by definition, Pair<Object>
is a subtype of Pair<? super Number>
Pair<? super Number>
-因此根据定义, Pair<Object>
是Pair<? super Number>
的子类型Pair<? super Number>
Pair<? super Number>
. Pair<? super Number>
。
After thinking about Makoto's answer for sometime I understood what it meant. 在思考了Makoto的答案一段时间后,我明白了它的含义。
Note: I am writing this answer in a format which I can easily understand for future reference (though his will be the accepted answer) 注意:我以易于理解的格式编写此答案,以备将来参考(尽管他将被接受)
Let's say we have the method in question defined like this (considering PECS), 假设我们有这样定义的方法(考虑PECS),
void wildcardsMethod(List<? super Pair<? super Number>> list) {
Pair<Number> pairOfNumbers = new Pair<Number>();
list.add(pairOfNumbers);
}
and we are calling the method with this argument ( assuming it was allowed ), 并且我们使用此参数调用该方法( 假设已允许 ),
List<Pair<Object>> listOfPairOfObjects = new ArrayList<Pair<Object>>();
wildcardsMethod(listOfPairOfObject);
Now, a Pair<Number>
object is added to listOfPairOfObjects
. 现在,将Pair<Number>
对象添加到listOfPairOfObjects
。
Also remember that the rules of PECS only apply to the list
reference in wildcardsMethod
and not the listOfPairOfObjects
reference. 还要记住, PECS的规则仅适用于wildcardsMethod
的list
引用,而不适用于listOfPairOfObjects
引用。
Hence I can do, 因此我可以
Pair<Object> pairOfObjects = listOfPairOfObjects.get(0);
Now, since a Pair<Number>
was added to the list in the method, I will receive a Pair<Number>
object when I expect a Pair<Object>
reference . 现在,由于将Pair<Number>
添加到该方法的列表中,因此当我希望使用Pair<Object>
引用时 , 我将收到Pair<Number>
对象 。
And these both are totally incompatible types. 这些都是完全不兼容的类型。 Hence the error. 因此,错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.