为什么使用基类进行方法引用会导致编译器错误

时间:2018-06-10 00:35:07

标签: java compiler-errors java-stream comparator

我使用Comparator对流进行排序,而且我遇到了一些我不理解的编译错误。

我们说我有以下课程:

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

为什么我会收到这些编译器错误?为什么在从rev2构建fwd时可以有效地规避它们?

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

1 个答案:

答案 0 :(得分:2)

正如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());
相关问题