4

在Effective Java中,在“使用有界通配符提高API灵活性”项中,在谈到PECS(producer-extends,consumer-super)的使用时,作者提到:

可比较对象始终是消费者,因此您通常应该使用 Comparable<? super T> 优先于 Comparable。比较器也是如此;因此,您通常应该使用 Comparator<? super T> 优先于 Comparator。

我不清楚为什么 Comparables 和 Comparators 被认为是消费者。

在讨论 PECS 的主题之一中,什么是 PECS(生产者扩展消费者超级)?,消费者通常将 Collection 称为某些泛型方法的参数。

而这里的 Comparable 只是一个接口。

任何人都可以分享一些见解吗?谢谢!

4

3 回答 3

5

可以对接口Consumer<T>Supplier<T>Supplier类似于生产者)进行一个很好的类比。AConsumer<T>是一个接受 a 的函数T,而 aSupplier<T>是一个返回 a 的函数T。请注意,我们谈论的是方法签名和返回类型,我们没有谈论方法的语义。这是 PECS 的核心属性:它独立于语义,可以仅根据所使用方法的签名和返回类型来确定。

查看Comparable<T>and Comparator<T>,我们发现两者都有方法 ( int compareTo(T)and int compare(T, T)) 接受,即消费, T's。

对于集合,我们必须查看如何使用集合,即我们使用的是生产者方法还是消费者方法:

  • 如果我们从集合(T get(int),迭代器,...)中检索数据,列表会为我们生成值,我们使用? extends T.
  • 如果我们使用集合来存储数据,(即我们调用add(T), addAll(Collection<T>), contains(T), ...),我们调用消费方法,因此该方法是我们数据的消费者并且我们使用? super T.
  • 如果我们使用集合来存储和检索值,那么集合同时充当消费者和生产者,因此我们必须使用精确的T,既不使用... extends ...也不使用... super ...
于 2020-08-12T22:16:03.607 回答
3

„<em>...我不清楚为什么 Comparables 和 Comparators 被视为消费者。...“</p>

C<T>任何时候泛型类的方法成员接受(即“<em>consumes”)类型为 的参数T,则该方法是s的消费者T

所以据说是由类型变量表示的类型Comparator<T>.compareTo(T o)的对象的“消费者” 。oT

于 2020-08-12T22:13:03.037 回答
3

当我们说“Comparable是消费者”时,我们实际上是指“接口的方法是消费者”。这是对您怀疑“Comparable只是一个界面”的答案。

查看其签名:https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Comparable.html#compareTo(T)

int compareTo​(T o)

它消耗泛型T,它不产生任何泛型对象。

于 2020-08-12T22:14:03.817 回答