Обобщения являются инвариантами, но компилируются без ошибок
Я получал ошибки несоответствия типов, пока я не реорганизовал код в это:
public final Stream<Map.Entry<E, Integer>> orderedStreamOfEntries() {
return this.m_map.entrySet()
.stream()
.sorted(Comparator.comparingInt(Entry::getValue))
.map(AbstractMap.SimpleImmutableEntry::new);
}
- Тип возврата
Stream<Entry<E, Integer>>
- Тип потока в конце этой процедуры
Stream<SimpleImmutableEntry<E, Integer>>
Параметр формального типа E
имеет это определение:
<E extends Enum<E> & MyCustomInterface>
Я не понимаю, почему это кажется приемлемым для компилятора. Поскольку дженерики Java инвариантны, даже если java.util.AbstractMap.SimpleImmutableEntry
инвентарь java.util.Map.Entry
Я бы сказал, что Stream<SimpleImmutableEntry<>>
не является подтипом возвращаемого типа, Stream<Entry<>>
,
1 ответ
Вы делаете две ошибки. Первый предполагает SimpleImmutableEntry::new
это Function<Entry, SimpleImmutableEntry>
* когда на самом деле это можно интерпретировать как Function<Entry, Entry>
что происходит, чтобы вернуть SimpleImmutableEntry
,
Во-вторых, посмотрите на подпись map()
:
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
Возвращая ? extends R
метод свободен для интерпретации R
в качестве суперкласса типа возврата лямбда, что означает даже Function<Entry, SimpleImmutableEntry>
может привести к Stream<Entry>
, или даже Stream<Object>
,
Фактическая интерпретация зависит от предполагаемого типа возврата, который в вашем случае Stream<Entry>
,
* Необработанные типы записей, используемые для краткости.