[英]java 8 list of optionals collect to list compilation error
我无法理解之间的区别
Stream<Optional<Integer>> optionalStream = Stream.of(
Optional.of(1),
Optional.empty(),
Optional.of(5));
List<Optional<Integer>> optionalList = optionalStream.collect(Collectors.toList());
哪个工作得很好,并且:
List<Optional<Integer>> 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<java.lang.Integer>
lower bounds: java.util.Optional<? extends java.lang.Object>
我已经减少了一些示例,并尝试使用-XDverboseResolution=all
编译以输出有关类型推断的信息:
final class One {
void one() {
Stream<Optional<Integer>> optionalStream = Stream.of(Optional.empty());
List<Optional<Integer>> optionalList = optionalStream.collect(Collectors.toList());
}
}
final class Two {
void two() {
List<Optional<Integer>> optionalList1 =
Stream.of(Optional.empty()).collect(Collectors.toList());
}
}
在Two
的情况下,看起来像Stream.of
的延迟实例化甚至在查看后续的collect
之前完成:
...
Two.java:9: Note: Deferred instantiation of method <T>of(T)
Stream.of(Optional.empty()).collect(Collectors.toList());
^
instantiated signature: (Optional<Object>)Stream<Optional<Object>>
target-type: <none>
where T is a type-variable:
T extends Object declared in method <T>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<Optional<Object>>
。
如果你看一下相应的输出为One
:
...
One.java:8: Note: Deferred instantiation of method <T>of(T)
Stream<Optional<Integer>> optionalStream = Stream.of(Optional.empty());
^
instantiated signature: (Optional<Integer>)Stream<Optional<Integer>>
target-type: Stream<Optional<Integer>>
where T is a type-variable:
T extends Object declared in method <T>of(T)
...
它是正确的,因为它知道目标类型。
我不能确切地说为什么延迟实例化在此时为Two
,因为我对应用类型推断的方式不太熟悉。
我认为这是因为Stream.of
的调用不被认为是poly表达式,但我无法真正说服自己为什么(请参阅编辑历史记录中的一些不连贯的ramblings)。
我建议的修复是将类型提示应用于Optional.empty()
,即Optional.<Integer>empty()
。 这具有在推理中更早获取Optional
的实际类型的效果,因此在延迟实例化时已知事件,尽管目标类型仍然是未知的:
final class Three {
void three() {
List<Optional<Integer>> optionalList1 =
Stream.of(Optional.<Integer>empty()).collect(Collectors.toList());
}
}
...
Three.java:9: Note: resolving method of in type Stream to candidate 1
Stream.of(Optional.<Integer>empty()).collect(Collectors.toList());
^
phase: BASIC
with actuals: Optional<Integer>
with type-args: no arguments
candidates:
#0 not applicable method found: <T#1>of(T#1...)
(cannot infer type-variable(s) T#1
(argument mismatch; Optional<Integer> cannot be converted to T#1[]))
#1 applicable method found: <T#2>of(T#2)
(partially instantiated to: (Optional<Integer>)Stream<Optional<Integer>>)
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>of(T#1...)
T#2 extends Object declared in method <T#2>of(T#2)
Three.java:9: Note: Deferred instantiation of method <T>of(T)
Stream.of(Optional.<Integer>empty()).collect(Collectors.toList());
^
instantiated signature: (Optional<Integer>)Stream<Optional<Integer>>
target-type: <none>
where T is a type-variable:
T extends Object declared in method <T>of(T)
...
Stream.of(...)
或Optional.empty()
是通用方法。 如果您不提供type参数,则会推断出它。 对于Optional.empty()
您将获得Optional<Object>
因此Stream.of(Optional.of(1), Optional.empty(), Optional.of(5))
将导致Stream<Optional<? extends Object>>
Stream<Optional<? extends Object>>
。
您可以通过在Stream.<Optional<Integer>>of(...)
Optional.<Integer>empty()
或Stream.<Optional<Integer>>of(...)
提供type参数来解决此问题。 我更喜欢第一个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.