Обобщения являются инвариантами, но компилируются без ошибок

Я получал ошибки несоответствия типов, пока я не реорганизовал код в это:

    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>,

* Необработанные типы записей, используемые для краткости.

Другие вопросы по тегам