[英]Why does the Streams API need a hint for generic type in this case?
以下無法編譯:
@NotNull String defaultFormatter(@Nullable Object value) {
if (value instanceof Collection) {
return ((Collection) value).stream()
.map(MyClass::defaultFormatter)
.collect(Collectors.joining(eol));
}
return String.valueOf(value);
}
特別是,當使用javac編譯時,錯誤將是:
Error:(809, 94) java: incompatible types:
java.lang.Object cannot be converted to
@org.jetbrains.annotations.NotNull java.lang.String
但以下編譯就好了:
@NotNull String defaultFormatter(@Nullable Object value) {
if (value instanceof Collection) {
Stream<String> stream = ((Collection) value).stream()
.map(MyClass::defaultFormatter);
return stream.collect(Collectors.joining(eol));
}
return String.valueOf(value);
}
唯一的區別是我引入了一個額外的變量。 請注意,我沒有強制轉換,因此沒有語義更改。
任何人都可以解釋為什么需要它?
這個答案的最重要部分基本上是Radiodef在上面的評論中所說的。 我不想偷的那些話,但下面的答案---
並沒有真正事先沒有解釋工作。
正如Radiodef所指出的,之所以在第一種情況下不起作用,是因為它使用的是原始類型Collection
。 相反,使用Collection<?>
,它將工作:
return ((Collection<?>) value).stream()
.map(MyClass::defaultFormatter)
.collect(Collectors.joining(eol));
它與顯式變量一起使用的原因是未經檢查的轉換。 請注意,以下內容會生成未經檢查的轉換警告:
Stream<String> stream = ((Collection) value).stream()
.map(MyClass::defaultFormatter);
RHS上表達式的實際類型是Stream
; 您可以將其強制轉換為Stream<String>
,如JLS Sec 5.1.9中所述 :
從原始類或接口類型(§4.8)
G
到G<T1,...,Tn>
形式的任何參數化類型都有未經檢查的轉換。
沒有變量你不能做同樣的事情的原因有點微妙。 這個答案更直接地解決了這個問題 :當你使用原始類型時, 所有泛型都會從類型中刪除,而不僅僅是與省略類型直接相關的泛型。
因此,當Stream
是raw時, Stream.collect
的類型是類型的擦除,當它是通用的時:
Stream.collect(Collector<? super T,A,R> collector)
返回R
; R
的擦除是Object
所以collect
調用的返回類型是Object
,正如您在此處觀察到的那樣。 這不能通過未經檢查的轉換自動強制轉換為List<String>
,因為它不是List
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.