Why does the Streams API need a hint for generic type in this case?(在这种情况下,为什么 Streams API 需要泛型类型的提示?)
问题描述
以下编译失败:
    @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 编译时,错误会是:
In particular, when compiled with javac, the error would be:
Error:(809, 94) java: incompatible types: 
      java.lang.Object cannot be converted to 
      @org.jetbrains.annotations.NotNull java.lang.String
但是下面的编译就好了:
But the following compiles just fine:
    @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);
    }
唯一的区别是我引入了一个额外的变量.请注意,我没有强制转换,所以没有语义变化.
The only difference would be that I introduced an extra variable. Note that I didn't cast, so no semantic change.
谁能解释为什么需要这样做?
Can anybody explain why is this needed?
推荐答案
这个答案的顶部基本上是 Radiodef 在上面的评论中说.我不想盗用这些话,但如果没有事先说明,--- 下面的答案实际上是行不通的.
This top part of this answer is basically what Radiodef said in comments above. I'm not wanting to steal those words, but the answer below the --- doesn't really work without the prior explanation.
正如 Radiodef 所指出的,这在第一种情况下不起作用的原因是因为它使用的是原始类型 Collection.相反,使用 Collection<?>,它会起作用:
As pointed out by Radiodef, the reason why this doesn't work in the first case is because it's using a raw type, Collection. Instead, use Collection<?>, and it will work:
        return ((Collection<?>) value).stream()
                    .map(MyClass::defaultFormatter)
                    .collect(Collectors.joining(eol));
它与显式变量一起工作的原因是未经检查的转换.请注意,以下内容会产生未经检查的转换警告:
The reason why it works with the explicit variable is because of unchecked conversion. Note that the following produces an unchecked conversion warning:
        Stream<String> stream = ((Collection) value).stream()
                     .map(MyClass::defaultFormatter);
RHS上表达式的实际类型是Stream;您可以将其强制转换为 Stream<String>,如 JLS Sec 5.1.9:
The actual type of the expression on the RHS is Stream; you're allowed to coerce that to a Stream<String>, as described in JLS Sec 5.1.9:
存在从原始类或接口类型(第 4.8 节)G 到 G.
There is an unchecked conversion from the raw class or interface type (§4.8)
Gto any parameterized type of the formG<T1,...,Tn>.
<小时>
没有变量你不能做同样的事情的原因有点微妙.这个答案更直接地解决了这个问题:当您使用原始类型时,所有泛型都会被删除从类型,而不仅仅是那些与省略的类型直接相关的.
The reason why you can't do the same without the variable is a bit more subtle. This answer addresses the issue more directly: when you use a raw type, all generics are erased from the type, not just ones directly related to the omitted type.
所以,Stream 为 raw 时的 Stream.collect 类型是泛型时类型的擦除:
So, the type of Stream.collect when the Stream is raw is the erasure of the type when it is generic:
Stream.collect(Collector super T,A,R> collector)返回一个R;R的擦除是Object
Stream.collect(Collector<? super T,A,R> collector)returns anR;- The erasure of 
RisObject 
所以 collect 调用的返回类型是 Object,正如您在此处看到的那样.这不能通过未经检查的转换自动强制转换为 List,因为它不是 List.
so the return type of the collect call is Object, as you observe here. This can't be automatically coerced to a List<String> via unchecked conversion because it's not List.
这篇关于在这种情况下,为什么 Streams API 需要泛型类型的提示?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在这种情况下,为什么 Streams API 需要泛型类型的提示?
				
        
 
            
        - 从 finally 块返回时 Java 的奇怪行为 2022-01-01
 - Safepoint+stats 日志,输出 JDK12 中没有 vmop 操作 2022-01-01
 - Jersey REST 客户端:发布多部分数据 2022-01-01
 - value & 是什么意思?0xff 在 Java 中做什么? 2022-01-01
 - Java包名称中单词分隔符的约定是什么? 2022-01-01
 - Eclipse 插件更新错误日志在哪里? 2022-01-01
 - 将log4j 1.2配置转换为log4j 2配置 2022-01-01
 - 如何使用WebFilter实现授权头检查 2022-01-01
 - Spring Boot连接到使用仲裁器运行的MongoDB副本集 2022-01-01
 - C++ 和 Java 进程之间的共享内存 2022-01-01
 
						
						
						
						
						