java 8选项列表收集列表编译错误

我无法理解之间的区别

Stream<Optional> optionalStream = Stream.of( Optional.of(1), Optional.empty(), Optional.of(5)); List<Optional> optionalList = optionalStream.collect(Collectors.toList()); 

哪个工作得很好,并且:

 List<Optional> optionalList1 = Stream.of( Optional.of(1), Optional.empty(), Optional.of(5)).collect(Collectors.toList()); 

我收到错误的地方

 Error:(138, 40) java: incompatible types: inference variable T has incompatible bounds equality constraints: java.util.Optional lower bounds: java.util.Optional 

我已经减少了一些示例,并尝试使用-XDverboseResolution=all编译以输出有关类型推断的信息:

 final class One { void one() { Stream> optionalStream = Stream.of(Optional.empty()); List> optionalList = optionalStream.collect(Collectors.toList()); } } final class Two { void two() { List> optionalList1 = Stream.of(Optional.empty()).collect(Collectors.toList()); } } 

Two的情况下,看起来Stream.of的延迟实例化甚至在查看后续的collect之前完成:

 ... Two.java:9: Note: Deferred instantiation of method of(T) Stream.of(Optional.empty()).collect(Collectors.toList()); ^ instantiated signature: (Optional)Stream> target-type:  where T is a type-variable: T extends Object declared in method of(T) Two.java:9: Note: resolving method collect in type Stream to candidate 0 Stream.of(Optional.empty()).collect(Collectors.toList()); ... 

(“解决方法collect是第一次提到collect

没有target-type来约束它; 实例化的签名显示它是Stream>

如果你看一个相应的输出:

 ... One.java:8: Note: Deferred instantiation of method of(T) Stream> optionalStream = Stream.of(Optional.empty()); ^ instantiated signature: (Optional)Stream> target-type: Stream> where T is a type-variable: T extends Object declared in method of(T) ... 

这是正确的,因为它知道目标类型。

我不能确切地说为什么延迟实例化在此时为Two ,因为我对应用类型推断的方式不够熟悉。

认为这是因为Stream.of的调用不被认为是一个多义表达式,但我无法真正说服自己为什么(请参阅编辑历史记录中的一些不连贯的ramblings)。


我建议的修复是将类型提示应用于Optional.empty() ,即Optional.empty() 。 这具有在推理中较早获取Optional的实际类型的效果,因此在延迟实例化时已知事件,尽管目标类型仍然是未知的:

 final class Three { void three() { List> optionalList1 = Stream.of(Optional.empty()).collect(Collectors.toList()); } } ... Three.java:9: Note: resolving method of in type Stream to candidate 1 Stream.of(Optional.empty()).collect(Collectors.toList()); ^ phase: BASIC with actuals: Optional with type-args: no arguments candidates: #0 not applicable method found: of(T#1...) (cannot infer type-variable(s) T#1 (argument mismatch; Optional cannot be converted to T#1[])) #1 applicable method found: of(T#2) (partially instantiated to: (Optional)Stream>) where T#1,T#2 are type-variables: T#1 extends Object declared in method of(T#1...) T#2 extends Object declared in method of(T#2) Three.java:9: Note: Deferred instantiation of method of(T) Stream.of(Optional.empty()).collect(Collectors.toList()); ^ instantiated signature: (Optional)Stream> target-type:  where T is a type-variable: T extends Object declared in method of(T) ... 

Stream.of(...)Optional.empty()是通用方法。 如果您不提供type参数,则会推断出它。 对于Optional.empty()您将获得Optional因此Stream.of(Optional.of(1), Optional.empty(), Optional.of(5))将导致Stream> Stream>

您可以通过在Stream.>of(...) Optional.empty()Stream.>of(...)提供type参数来解决此问题。 我更喜欢第一个。