我已經減少了例子位,並試圖編譯與-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()'。感覺你不應該這樣做,但是這就是它在當前實現中的樣子。 –