为什么在Java的PECS通配符类型中,Comparable和Comparator是消费者?

huangapple go评论75阅读模式
英文:

Why Comparable and Comparator are consumers in PECS wildcard types in Java

问题

在《Effective Java》中,在项目“使用有界通配符以增加API的灵活性”中,当讨论PECS(生产者-扩展,消费者-超级)的使用时,作者提到:

> Comparables始终是消费者,因此通常应首选使用Comparable<? super T>而不是Comparable<T>。比较器也是如此;因此,通常应首选使用Comparator<? super T>而不是Comparator<T>。

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

在讨论PECS的一个主题中,https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super,消费者通常是指将Collection作为某个通用方法的参数。

而在这里,Comparable只是一个接口。

有人能分享一些见解吗?谢谢!

英文:

In Effective Java, in the item "Use bounded wildcards to increase API flexibility", when talking about the usage of PECS (producer-extends, consumer-super), the author mentioned that:

> Comparables are always consumers, so you should generally use Comparable<? super T> in preference to Comparable<T>. The same is true of comparators; therefore, you should generally use Comparator<? super T> in preference to Comparator<T>.

It is not clear to me why Comparables and Comparators are considered consumers.

In one of the topic discussing PECS, https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super, the consumer is usually referring to a Collection as a parameter for some generic method.

While here Comparable is just an interface.

Can anyone share some insights? Thanks!

答案1

得分: 5

以下是翻译好的部分:

一个很好的类比可以与接口 Consumer&lt;T&gt;Supplier&lt;T&gt; 进行。(Supplier 类似于生产者)。Consumer&lt;T&gt; 是一个接受 T 的函数,而 Supplier&lt;T&gt; 是一个返回 T 的函数。请注意,我们谈论的是方法签名和返回类型,我们没有涉及方法的语义。这是PECS的核心属性:它与语义无关,完全可以根据所使用的方法的签名和返回类型来确定。

观察 Comparable&lt;T&gt;Comparator&lt;T&gt;,我们发现两者都有方法 (int compareTo(T)int compare(T, T)),这些方法接受,即消耗 T 的实例。

对于集合,我们必须看我们如何使用集合,即是否使用生成器方法或消费器方法:

  • 如果我们从集合中检索数据(T get(int),迭代器等),列表为我们生成值,我们使用 ? extends T
  • 如果我们使用集合来存储数据(即我们调用 add(T)addAll(Collection&lt;T&gt;)contains(T)等),我们调用消费方法,因此该方法是我们数据的消费者,我们使用 ? super T
  • 如果我们使用集合既用于存储又用于检索值,那么集合同时充当生产者和消费者,因此我们必须使用精确的 T,既不使用 ... extends ... 也不使用 ... super ...
英文:

A nice analogy can be drawn to the interfaces Consumer&lt;T&gt; and Supplier&lt;T&gt; (with Supplier being analogous to Producer). A Consumer&lt;T&gt; is a function that takes in a T, while a Supplier&lt;T&gt; is a function that returns a T. Notice that we are talking about method signatures and return type, we say nothing about the semantics of the method. This is a core property of PECS: it is independent of the semantics and can be determined solely on the signature and return type of the methods used.

Looking at Comparable&lt;T&gt; and Comparator&lt;T&gt;, we find that both have methods (int compareTo(T) and int compare(T, T)) that take in, i.e. consume, T's.

For the collections, we have to look on how we use the collection, i.e. if we are using producer- or consumer-methods:

  • If we retrieve data from the collection (T get(int), iterator, ...), the list produces values for us and we use ? extends T.
  • If we use the collection to store data, (i.e. we call add(T), addAll(Collection&lt;T&gt;), contains(T), ...), we call consuming methods, thus the method is a consumer of our data and we use ? super T.
  • If we use a collection to both store and retrieve values, the collection acts as a consumer and producer at the same time, thus we have to use the precise T, neither using ... extends ... nor ... super ....

答案2

得分: 3

"不清楚为什么可比较对象(Comparables)和比较器(Comparators)被认为是消费者。"

每当泛型类C的方法成员“接受”(即“消耗”)一个类型为T的参数时,那么该方法被称为“T的消费者”。

因此,Comparator.compareTo(T o) 被称为是类型变量T表示的类型的对象o的“消费者”。

英文:

> „&hellip;It is not clear to me why Comparables and Comparators are considered consumers.&hellip;“

Anytime a method member of a generic class C&lt;T&gt;, takes in (i.e. „consumes“) an argument that is of type T, then that method is a consumer of Ts.

So Comparator&lt;T&gt;.compareTo(T o) is said to be a „consumer“ of the o object of the type represented by the type variable T.

答案3

得分: 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,不生成任何泛型对象。

英文:

When we say "Comparable is a consumer", we actually mean "the method of the interface is a consumer". This is an answer to your doubt that "Comparable is just an interface."

See its signature: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Comparable.html#compareTo(T)

int compareTo​(T o)

It consumes the generic T, it does not produce any generic object.

huangapple
  • 本文由 发表于 2020年8月13日 06:03:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/63385298.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定