Я даже не пытаюсь выяснить, почему компилятор не принимает эту конструкцию. Когда дело доходит до вывода типов и подстановочных знаков, многие вещи, которые выглядят так, как будто они должны работать, не делают.
Самое простое решение - это предоставить явный тип для общего вызова c вызова map
:
return getFooArgs(bar)
.<List<? extends AbstractEntityDto>>map(entityService::getListWithFooArgs)
.orElseGet(entityService::getListNoArgs);
Как правило, следует избегать подстановочных знаков в типах возврата . Нет смысла носить с собой подстановочный знак. Напротив, когда у вас действительно есть код, работающий с List<ConcreteEntityDto>
, и вам нужно передать его методу, который должен быть в состоянии справиться с большим количеством случаев, объявив тип параметра с подстановочным знаком, например List<? extends AbstractEntityDto>
, принять List<ConcreteEntityDto>
, а также List<SomeOtherEntityDto>
, очень полезно.
Обратите внимание, что при
List<? extends AbstractEntityDto> list = …
вы можете сделать
List<AbstractEntityDto> view = Collections.unmodifiableList(list);
для последующей обработки который не пытается изменить список. Оболочка, возвращаемая unmodifiableList
, предотвращает любые попытки вставить элементы в список неизвестных подтипов AbstractEntityDto
, но может гарантировать возвращение экземпляров AbstractEntityDto
для всех методов запроса. Вот почему это изменение типа действительно.