为什么使用基 class 作为方法引用会导致编译器错误

Why does using a base class for a method reference cause a compiler error

我正在使用 Comparators 对流进行排序,但遇到了一个我不理解的编译器错误。

假设我有以下 类:

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

我正在创建两个比较器以按日期对 Sub 进行排序,一个按自然顺序,一个按相反顺序。以下代码编译:

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

为什么会出现这些编译器错误?为什么我可以在从 fwd 构建 rev2 时有效地绕过它们?

(我正在使用 Eclipse Oxygen.3a (4.7.3) 和 Java v1.8。0_162 如果相关的话。)

如本 answer 所述,目标输入因调用 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());