Bon*_*i69 5 java generics lambda covariance contravariance
我对协方差和相反性有些困惑。我们是否说过,在Java中,当我们使用时通常是矛盾的? super X。
现在阅读我的书,我理解了以下概念:
这是矛盾的:
method(Predicate<? super X> pred)
Run Code Online (Sandbox Code Playgroud)
但这是协变的:
method(List<? super X> list) //And then we use add for a list of course
Run Code Online (Sandbox Code Playgroud)
这个概念没有明确地写成我要问你的方式,所以我想知道,这个定义正确吗?如果是,为什么第一个是协变的,为什么最后一个是协变的(如果两者都使用super关键字)?
我们不经常谈论 Java 中的方差,人们通常只应用PECS。
\n您的两个示例在方差方面是相同的,因为内部的实际方法定义是什么Predicate或List评估其方差并不重要。
那么这里是什么?
\n好吧,让 \xe2\x80\x99s 说我们有Cat extends Animal和method(List<? super Cat> list)(或与 相同Predicate)。此方法将接受List<? super Cat>、List<Cat>、List<Animal>甚至List<? super Animal或List<Object>作为参数,即List其泛型类型是 的超类型Cat。
使用符号\xe2\x89\xa4(另请参阅此答案),我们看到? super反转关系:Cat \xe2\x89\xa4 Animal暗示List<Animal> \xe2\x89\xa4 List<? super Cat>,因此这是交换类型时的逆变。
相反,List<Cat> \xe2\x89\xa4 List<? extends Animal>,即您可以将类型的值分配List<Cat>给类型 的变量/参数List<? extends Animal>。由于它不交换类型 ( Cat \xe2\x89\xa4 Animal),因此这是协方差。(另请参阅如何在 Java 泛型中使用逆变?)
引用相同的维基百科文章 \xe2\x80\x99s关于使用站点差异注释(通配符)的部分(如 Java 中):
\n\n\n通配符类型的上界是协变的(下界也是逆变的)。总的来说,给定一个像 的通配符类型
\nC<? extends T>,可以通过三种方式形成子类型:通过专门化类C、指定更紧密的界限、或者用特定类型T替换通配符。?
(您可以在上面替换C<? extends T>为,它只是产生下限而不是上限)。C<? super T>T