Распознавание типов в компараторе Java
Пусть есть некий класс Test
, содержащий поле field
типа int
:
class Test {
private final int field;
public int getField() {
return field;
}
public Test(int field) {
this.field = field;
}
@Override
public String toString() {
return String.valueOf(field);
}
}
Есть список List<Test> list
объектов класса Test
, который мы хотим отсортировать посредством компаратора по полю field
.
Компаратор для такой сортировки может выглядеть так:
list.sort(Comparator.comparingInt(test -> test.getField()));
Понятно, что тут можно сократить до "method reference", но об этом речь позже.
Метод comparingInt()
ожидает на вход тип ToIntFunction<? super T>
, где T
в нашем случае является классом Test
. Очевидно, что в этой лямбде тип test
распознаётся как Test
, мы спокойно вызываем его метод getField()
и получаем корректную лямбду.
Но если написать вот так:
list.sort(Comparator.comparingInt(test -> test.getField()).reversed());
то компилятор будет ругаться, говоря, что test
имеет тип Object
, в котором, разумеется, метода getField()
нет.
Убрать эту ошибку можно тремя разными способами:
- заместо лямбды сделать "method reference"
- оставить лямбду, но привести её к типу
ToIntFunction<Test>
- оставить лямбду, но явно указать в ней тип переменной
test
какTest
Не считая, конечно, того варианта, когда мы создаём свой отдельный класс, реализующий Comparator<Test>
.
Собственно, вопрос: почему вообще возникает такая ошибка? Из-за чего получается так, что при последующем вызове метода reversed()
Java отказывается распознавать тип test
как Test
?
Причём такой же эффект возникает, если к создаваемому компаратору пытаться применять, например, метод thenComparing()
.