2017-07-27 68 views
2

我得到类型不匹配的错误,直到我重构代码,以这样的:泛型是不变的,但这种编译没有错误

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实现了​​,我也会说Stream<SimpleImmutableEntry<>>不是返回类型的子类型Stream<Entry<>>

+0

从类定义中定义的'E'是什么? – ArtB

+0

@ArtB:我已将定义编辑到问题 – scottb

+0

如果有疑问在调试时,我建议将流上的每个操作作为对特定变量的赋值进行拆分。使用具有重构支持的IDE使得这个微不足道。这会让你看到类型的演变。 – ArtB

回答

2

你犯了两个错误。第一个假设SimpleImmutableEntry::newFunction<Entry, SimpleImmutableEntry> *,实际上它可以解释为Function<Entry, Entry>,其中恰好会返回 a SimpleImmutableEntry

其次,看该签名map()

<R> Stream<R> map(Function<? super T, ? extends R> mapper) 

通过返回? extends R,该方法也可以自由解释R作为超的lambda表达式返回类型,这意味着即使是Function<Entry, SimpleImmutableEntry>可能导致Stream<Entry>,或甚至Stream<Object>

实际的解释取决于推断的返回类型,在你的情况下是Stream<Entry>

*为简洁起见,使用原始条目类型。

+0

<<<首先假设SimpleImmutableEntry :: new是一个函数 *,实际上它可以解释为函数,它恰好返回SimpleImmutableEntry。>>> 看起来好像成为关键, – ArtB

+0

@scottb是的,这是一回事。重点是'Function '可以(读取:必须)返回'Entry'的子类。 – shmosel

+0

是的,我明白你在说什么。令我困惑的是,我的IDE将'map()'函数的返回类型显示为Stream >'。如果这确实是返回类型,那么似乎应该有一个错误。 – scottb