下面的方法編譯沒有問題:
static Stream<Optional<? extends Number>> getNumbers(Stream<Number> numbers) {
return numbers.map(Optional::of);
}
但是如果我像這樣添加一個簡單的過濾:
static Stream<Optional<? extends Number>> getNumbers2(Stream<Number> numbers) {
return numbers.map(Optional::of).filter(number -> true);
}
它會產生以下錯誤:
不兼容的型別:java.util.stream.Stream<java.util.Optional<java.lang.Number>> 不能轉換為 java.util.stream.Stream<java.util.Optional<? 擴展 java.lang.Number>>
在 openJdk-11 和 openJdk-17 上測驗。
我希望他們都做同樣的事情(要么編譯正常,要么都產生相同的編譯錯誤),所以我真的很困惑:這里的一般規則是什么解釋了為什么第一種方法編譯正常而第二種方法編譯正常才不是?謝謝!
uj5u.com熱心網友回復:
與Stream<Optional<? extends Number>>第一種情況下的回傳型別的兼容性不是通過自己numbers.map(Optional::of)回傳 aStream<Optional<? extends Number>>來獲得的;numbers.map(...)由于它是一個泛型方法,編譯器會推斷它的回傳型別:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
而Stream.filter()不是:
Stream<T> filter(Predicate<? super T> predicate);
因此,在第一種情況下,編譯器getNumbers在推斷 的型別時可以考慮回傳陳述句的背景關系(的型別)numbers.map(...)。
編譯器numbers.map(...)在第二種情況下不能做同樣的事情,因為有后續的鏈式呼叫,這可能會進一步改變型別,所以在這個階段很難猜測正確的推斷應該是什么。因此,最具體的可能型別被假定為numbers.map(...)( Stream<Optional<Number>>) 并進一步由 進行filter(...)。
作為一個不同的例子來說明這一點,請弄清楚為什么這兩個編譯(List.of()畢竟是相同的代碼):
static List<String> stringList() {
return List.of();
}
static List<Integer> intList() {
return List.of();
}
現在,為什么會失敗:
static List<String> stringList() {
return List.of().subList(0, 0);
}
這是因為List.subList(...)不會E在背景關系中推斷回傳串列的型別(即該方法不是通用的),它攜帶List實體的E型別,List.of()在這種情況下,它被默認為Object(是的,當你有時return List.of();,回傳型別推斷開始,強制編譯器找出意圖是使Ematch String,方法的回傳型別中的型別引數)。請注意,這比這更復雜,有些角落推理無法按預期/預期作業。
簡短的回答:return numbers.map(Optional::of)利用型別推斷作為map()泛型,而filter()不是期望EofStream<E>被攜帶。和numbers.map(Optional::of),E是Optional<Number>, 不是Optional<? extends Number>,并filter帶有。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/389716.html
下一篇:將物件型別作為引數傳遞給方法?
