java - 为什么在这种情况下 Streams API 需要泛型类型的提示?

标签 java generics java-stream inferred-type

以下编译失败:

    @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 中所述:

There is an unchecked conversion from the raw class or interface type (§4.8) G to any parameterized type of the form G<T1,...,Tn>.


没有变量就不能做同样的事情的原因有点微妙。 This answer addresses the issue more directly : 当您使用原始类型时,所有 泛型都会从该类型中删除,而不仅仅是与省略的类型直接相关的泛型。

因此,Stream.collect 的类型当Stream is raw 是泛型时类型的删除:

  • Stream.collect(Collector<? super T,A,R> collector)返回 R ;
  • 删除 RObject

所以 collect 的返回类型电话是Object ,正如您在这里观察到的那样。这不能自动强制为 List<String>通过未经检查的转换,因为它不是 List .

关于java - 为什么在这种情况下 Streams API 需要泛型类型的提示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44700744/

相关文章:

Java:如何添加两个整数流并生成一个新流

java - 为什么我的客户端关闭连接

java - Tomcat 始终创建新 session

java - Google Play 应用内结算 onPurchasesUpdated() 错误响应代码 -1

c# - 如何将通用 List<T> 转换为 List?

Java 8 使用流重写一个复杂的 for 循环

java - 战列舰不能放在边缘

java - 如何修复Java中的 "type argument S is not within bounds of type-variable E"

c# - Func<> 的 List<>,具有通用返回类型的编译错误,但为什么呢?

java - 使用 "id"字段更新列表的子部分