以下三个签名之间有什么区别?
static <T> void foo(List<T>, Comparator<? super T>);
static <T> void bar(List<? extends T>, Comparator<T> );
static <T> void baz(List<? extends T>, Comparator<? super T>);
我知道Generics中extends
和super
的含义。我的问题是foo
,bar
和baz
之间是否存在差异。我是否应该使其中一个参数保持不变,另一个变量在适当的方向上,或者我应该使它们两个变体?它有所作为吗?
答案 0 :(得分:5)
PECS - Producer扩展,消费者超级。
解释这个“规则”:
extends
表示通用化对象生成该类型的元素。当它是一个集合时,它意味着你只能从集合中获取元素,但不能将它们放入。比较器super
表示对象使用所选类型的对象。因此,您可以添加到集合中,但不能从中读取。关于Comparator
,我认为这没有任何区别。通常,它会是<? super T>
,因为比较器使用对象,但在所有三种情况下,您都可以安全地调用Collections.sort(list, comparator);
(其签名为<? super T>
)
答案 1 :(得分:2)
唯一的区别是T
是否代表List
的类型参数,Comparator
或其中的某些内容。
就调用者而言,三种方法签名是等效的,即只要其中一个可以使用,其他签名也可以使用。
对于方法实现foo
可能是最方便的,因为它允许修改列表而无需额外的捕获转换,这需要委托给辅助方法。
答案 2 :(得分:1)
我认为? extends T
表示List
可能是从T派生的任何类型的通用,而List<T>
只能是List
T
而不是任何派生类。