После обширных исследований я наткнулся на это сообщение об ошибке .Этот отчет ссылается на этот раздел в спецификации Java, который дает вам базовые знания о том, как все это работает.Имейте это в виду, потому что это будет необходимо позже.
Проблема может быть уменьшена, чтобы выглядеть следующим образом (хотя я знаю, что это не то, что вы хотите, это воспроизведет ошибку):
Supplier<Boolean> o = identity((x) -> true);
Итак, я считаю, что проблема заключается в том, как Java решает, какими должны быть дженерики типов.Когда вы указываете Supplier<Boolean>
в качестве типа o
, он сообщает компилятору, что тип возвращаемого значения identity
должен быть Supplier<Boolean>
.
Теперь в вашем примере у вас нетпеременная, которая хранит вывод identity
.Это та часть, которая вытекает из спецификации.Всякий раз, когда Java получает универсальный тип, этот тип должен находиться в определенных пределах.В основном это означает, что в иерархии расширения есть определенный самый высокий класс и самый низкий класс.
Например, если у вас есть класс C
, который расширяет класс B
, который также расширяет класс A
, вашверхняя граница может быть C
, а нижняя граница может быть A
.Таким образом, вы можете использовать что угодно от A
до C
.Это всего лишь пример того, как работают границы.
Это в основном то, что происходит в вашем классе.Поскольку вы не указываете String
в качестве типа параметра, Java не знает, какой это может быть тип.Так как он не знает, он делает все возможное, чтобы привести его к правильному типу, но поскольку родовые типы настолько неоднозначны, он не может привести его к правильному типу.Он как-то решает использовать Supplier<Boolean>
в качестве базовой линии (вероятно, также определенной где-то в спецификации) и ожидает, что это будет тип возвращаемого значения.Так как он не получает это, он выдает ошибку.Почему он не решает проверить, является ли это Boolean
, выше моего понимания, но согласно отчету об ошибке все работает так, как задумано.
Некоторые потенциальные исправления могут выглядеть следующим образом:
Recreation.assertTrue(identity((Function<String, Boolean>) (x) -> Boolean.TRUE));
Recreation.assertTrue((Boolean) identity((x) -> Boolean.TRUE));
Или просто неявно сообщая ему, какой тип параметра.
Recreation.assertTrue(identity((String x) -> Boolean.TRUE));
Я знаю, что у меня нет лучшего понимания этого конкретного обстоятельства, но это должно дать вам хотя бы базовую оценкупонимание того, как работает вся система.