Optional<B>
не является подтипом Optional<A>
.В отличие от других языков программирования, система универсальных типов Java не знает «типы только для чтения» или «параметры типа вывода», поэтому она не понимает, что Optional<B>
предоставляет только экземпляр B
и может работать в местах, где *Требуется 1005 *.
Когда мы пишем оператор, такой как
Optional<A> o = Optional.of(new B());
Вывод типа Java использует целевой тип, чтобы определить, что мы хотим, чтобы
Optional<A> o = Optional.<A>of(new B());
, который действителенnew B()
может использоваться, когда требуется экземпляр A
.
То же самое относится к
return Optional.of(
items.stream()
.map(s -> new B())
.findFirst()
.get()
);
, где объявленный тип возвращаемого значения метода используется для вывода аргументов типаOptional.of
вызов и передача результата get()
, экземпляр B
, где требуется A
, действителен.
К сожалению, этот вывод целевого типа не работает через цепочечные вызовыпоэтому для
return items.stream()
.map(s -> new B())
.findFirst();
он не используется для вызова map
.Таким образом, для вызова map
вывод типа использует тип new B()
, и его тип результата будет Stream<B>
.Вторая проблема заключается в том, что findFirst()
не является универсальным, вызов его для Stream<T>
неизменно приводит к Optional<T>
(а универсальные шаблоны Java не позволяют объявлять переменную типа, такую как <R super T>
, поэтому даже невозможно произвестиOptional<R>
с нужным типом здесь).
→ Решение состоит в том, чтобы предоставить явный тип для вызова map
:
public Optional<A> getItems(List<String> items){
return items.stream()
.<A>map(s -> new B())
.findFirst();
}
Просто для полноты, как сказано, findFirst()
не является универсальным и, следовательно, не может использовать целевой тип.Объединение в цепочку универсального метода, допускающего изменение типа, также решило бы проблему:
public Optional<A> getItems(List<String> items){
return items.stream()
.map(s -> new B())
.findFirst()
.map(Function.identity());
}
Но я рекомендую использовать решение для предоставления явного типа для вызова map
.