Java 泛型是不变的,但编译时不会出错

Java 泛型是不变的,但编译时不会出错,java,generics,invariance,Java,Generics,Invariance,我遇到了类型不匹配错误,直到我将代码重构为: public final Stream<Map.Entry<E, Integer>> orderedStreamOfEntries() { return this.m_map.entrySet() .stream() .sorted(Comparator.comparingInt(Entry::getValue))

我遇到了类型不匹配错误,直到我将代码重构为:

    public final Stream<Map.Entry<E, Integer>> orderedStreamOfEntries() {
        return this.m_map.entrySet()
                .stream()
                .sorted(Comparator.comparingInt(Entry::getValue))
                .map(AbstractMap.SimpleImmutableEntry::new);            
    }

我不明白为什么编译器似乎可以接受这一点。因为Java泛型是不变的,即使
Java.util.AbstractMap.SimpleImmutableEntry
实现了
Java.util.Map.Entry
,我会说
Stream
不是返回类型的子类型,
Stream

您犯了两个错误。第一个是假设
SimpleImmutableEntry::new
是一个
函数
*,而实际上它可以解释为一个
函数
,它恰好返回一个
SimpleImmutableEntry

第二,看看签名:


流图(函数类定义中的
E
的定义是什么?@ArtB:我已经将定义编辑到了问题中,当调试时有疑问时,我建议将流上的每个操作作为一个特定变量的赋值断开。使用支持重构的IDE使这变得很简单。这将让你看到类型的演变。这似乎是关键,@scottb是的,这是一样的。问题是,
函数
可能(读:必须)返回
条目
的子类。是的,我理解你的意思。让我困惑的是,我的IDE显示了
映射()中的返回类型
函数为
。如果这确实是返回类型,那么似乎应该有错误。@scottb可能只是IDE中的一个bug。类型推断是出了名的很难正确。@scottb这很奇怪,因为添加scottb是为了让IDE使用与javac编译器本身相同的代码。我相信除了Eclipse以外的所有IDE进行了切换(IIRC是因为他们需要在后台支持连续编译)。
<E extends Enum<E> & MyCustomInterface>
<R> Stream<R> map(Function<? super T, ? extends R> mapper)