我已经减少了例子位,并试图编译与-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
调用不被认为是多晶硅的表情,但我真的不能相信自己,为什么(见编辑历史有些语无伦次随笔)。
我建议的解决方法是一种提示适用于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。<可选>(/ * etc * /'? –
yes!为什么会发生这种情况? –
好吧,你只是给类型推理算法一些更多的限制。实际上,更容易添加的会是'可选。 empty()'。感觉你不应该这样做,但是这就是它在当前实现中的样子。 –