Почему использование базового класса для ссылки на метод вызывает ошибку компиляции - PullRequest
0 голосов
/ 10 июня 2018

Я использую Comparator s для сортировки потоков, и я столкнулся с ошибкой компилятора, которую я не понимаю.

Допустим, у меня есть следующие классы:

class Base {
    private LocalDate date;
    public LocalDate getDate() { return date; }
    ...
}
class Sub extends Base { ... }

Я создаю два компаратора для сортировки Sub s по их дате, один по естественному порядку и один в обратном порядке.Следующий код компилируется:

Comparator<Sub> fwd = Comparator.comparing(Sub::getStartDate);
Comparator<Sub> rev1 = Comparator.comparing(Sub::getStartDate).reversed();
Comparator<Sub> rev2 = fwd.reversed();

Понимая, что getDate() определено на Base, я подумал, что попробую следующее:

Comparator<Sub> fwd = Comparator.comparing(Base::getStartDate);
Comparator<Sub> rev1 = Comparator.comparing(Base::getStartDate).reversed();  // Compiler error
Comparator<Sub> rev2 = fwd.reversed();  // OK

Удивительно (для меня),код для rev2 компилируется нормально, в то время как код для rev1 вызывает следующие ошибки:

Cannot infer type argument(s) for <T, U> comparing(Function<? super T, ? extends U>)
The type Base does not define getStartDate(Object) that is applicable here

Почему я получаю эти ошибки компилятора?И почему я могу эффективно обойти их при сборке rev2 из fwd?

(я использую Eclipse Oxygen.3a (4.7.3) и Java v1.8.0_162, если это актуально.)

1 Ответ

0 голосов
/ 10 июня 2018

Как указано в этом ответе , типизацию цели нарушает присутствие вызова reversed():

Comparator<Sub> rev1 =
    Comparator.comparing(Base::getStartDate)
              .reversed(); // Compiler error - incompatible types

Похоже, что в этой ситуации компилятор выводит следующееаргументы типа:

Comparator<Sub> rev1 =
    Comparator.<Base, LocalDate>comparing(Base::getStartDate)
              .reversed(); // Compiler error - incompatible types

Чтобы избавиться от ошибки, вы можете явно указать аргументы типа:

Comparator<Sub> rev1 =
    Comparator.<Sub, LocalDate>comparing(Base::getStartDate)
              .reversed(); // Okay, no problem

или использовать два аргумента Comparator.comparing():

Comparator<Sub> rev1 =
    Comparator.comparing(Base::getStartDate, Comparator.reverseOrder());
...