为什么`Stream.collect`类型安全,而'Stream.toArray(IntFunction <A []>)`不是?

muu*_*ued 17 java types java-8 java-stream

请考虑以下代码片段

String strings[] = {"test"};
final List<String> collect = java.util.Arrays.stream(strings).collect(java.util.stream.Collectors.toList());
final Double[] array = java.util.Arrays.stream(strings).toArray(Double[]::new);
Run Code Online (Sandbox Code Playgroud)

Java的为什么能保证在收集情况的正确类型(改变泛型类型的收集到例如双导致编译时错误),但不是在阵列情况下(编译罚款,尽管apply(int)Double[]::new给出了一个Double[],而不是一个Object[],而是抛出ArrayStoreException如果上面使用不正确)?

什么是不改变给定生成的情况下,编译时错误的最好方式,我改变流的类型IntFunctiontoArray电话吗?

nos*_*sid 12

该方法的签名Stream::toArray如下.请注意,类型参数TA完全无关.

public interface Stream<T> {
    <A> A[] toArray(IntFunction<A[]> generator);
}
Run Code Online (Sandbox Code Playgroud)

ReferencePipeline.java的源代码中,您可以找到以下注释:

由于AU(不可能声明它A是上限U)无关,因此不会进行静态类型检查.因此使用原始类型,并且假设A == U,而不是传播的分离AU 在整个代码库.U永远不会检查运行时类型是否与运行时类型的组件类型相等A[].当一个元件被存储在将被执行的运行时检查A[],因此,如果A不是超类型的U一个ArrayStoreException将被抛出.

  • @muued请注意`<A super T>`在语法上是*在类型声明中是不可能的.你只能有`?超级T`作为一种类型,但你无法捕获`?`.这与`X extends T`相反,可以捕获`?延伸T`.它在创建泛型时从Java中省略,因为它被认为*不够有用*. (8认同)
  • @skiwi这个问题并不是流API独有的.[`Collection.toArray(T [])`](https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#toArray(T []))同样有效用例,所以如果那不足以支持`super`,那就没有理由了. (2认同)