簡體   English   中英

在這種情況下,為什么Streams API需要提示泛型類型?

[英]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) GG<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM