Why does the Streams API need a hint for generic type in this case?

我的梦境 提交于 2019-11-29 14:49:38

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.

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);

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:

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>.


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.

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) returns an R;
  • The erasure of R is Object

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!