Search code examples
javacollections

Why java.util.Comparator.reversed api does not work with Generic class


The following code only cannot compile in case 4:


  static class Foo {
    int seq;
    public Foo(int seq) {
      this.seq = seq;
    }

    public int getSeq() {
      return this.seq;
    }
  }

  static class Bar<T> {
    T seq;
    public Bar(T seq) {
      this.seq = seq;
    }

    public T getSeq() {
      return this.seq;
    }
  }

  public static void main(String[] args) {
    List<Foo> foos = List.of(new Foo(1), new Foo(2));

    // case 1 can compile
    List<Foo> fooRet1 = foos.stream()
        .sorted(Comparator.comparing(Foo::getSeq))
        .toList();
    // case 2 can compile
    List<Foo> fooRet2 = foos.stream()
        .sorted(Comparator.comparing(Foo::getSeq).reversed())
        .toList();

    List<Bar<Integer>> bars = List.of(new Bar<Integer>(1), new Bar<Integer>(2));
    // case 3 can compile
    List<Bar<Integer>> barRet1 = bars.stream()
        .sorted(Comparator.comparing(Bar::getSeq))
        .toList();
    // case 4 cannot compile
    // intellij IDEA draws a red line under Bar::getSeq, it says:
    // Non-static method cannot be referenced from a static context
    // which is wired
    List<Bar<Integer>> barRet2 = bars.stream()
        .sorted(Comparator.comparing(Bar::getSeq).reversed())
        .toList();
  }

Where does this limitation come from?


Solution

  • This is just a weakness in the Java compiler, that it couldn't infer the generic type of Bar while using reversed.

    You could explicitly add the genetic type of Bar

    List<Bar<Integer>> barRet2 = bars.stream()
            .sorted(Comparator.comparing(Bar<Integer>::getSeq).reversed())
            .toList();
    

    Relevant question https://stackoverflow.com/a/25173599/1477418