Issue with Comparator.comparing

B. Blaser bsrbnd at gmail.com
Mon Dec 17 12:36:20 UTC 2018


On Fri, 14 Dec 2018 at 16:28, Maurizio Cimadamore
<maurizio.cimadamore at oracle.com> wrote:
>
> I get that there are other ways to make the example working. But the API says:
>
> "Accepts a function that extracts a Comparable sort key from a type T, and returns a Comparator<T> that compares by that sort key."
>
> There's no other note in the API which hints at the fact that it might spectacularly fail because of heap pollution. And the fact that it is a synthetic cast that is failing, is strongly hinting at something at odds with the type-system.
>
> Maurizio

I agree there's something odd, but I really believe this isn't when
capturing the receiver which still ends up with a type variable (JLS
§5.1.10), the key extractor remaining generic and not instantiated.

As I said previously, the issue might be in the following expression:

  (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));

in 'Comparator::comparing':

http://hg.openjdk.java.net/jdk/jdk/file/dcbb71b9e7c0/src/java.base/share/classes/java/util/Comparator.java#l469

which is where 'keyExtractor' is "instantiated" to the type of c1 and
c2 which is assumed to be the same, 'T' in this case:

http://hg.openjdk.java.net/jdk/jdk/file/dcbb71b9e7c0/src/java.base/share/classes/java/util/Comparator.java#l468

I don't think there's any type system issue here, the API simply
requires all elements to be of the same type 'T' and thus returning
keys comparable between themselves (U extends Comparable<? super U>):

http://hg.openjdk.java.net/jdk/jdk/file/dcbb71b9e7c0/src/java.base/share/classes/java/util/Comparator.java#l465

This assertion being wrong in your example as 'T = ? super Foo<?>' and
keys aren't always comparable between themselves.

The doc should simply says something like here under.

What do you think?
Bernard

diff --git a/src/java.base/share/classes/java/util/Comparator.java
b/src/java.base/share/classes/java/util/Comparator.java
--- a/src/java.base/share/classes/java/util/Comparator.java
+++ b/src/java.base/share/classes/java/util/Comparator.java
@@ -459,6 +459,7 @@
      *         Comparable} sort key
      * @return a comparator that compares by an extracted key
      * @throws NullPointerException if the argument is null
+     * @throws ClassCastException if sort keys aren't comparable
between themselves
      * @since 1.8
      */
     public static <T, U extends Comparable<? super U>> Comparator<T> comparing(


More information about the compiler-dev mailing list