Java8流和类型转换

时间:2014-03-15 16:06:32

标签: java casting java-8 java-stream

有人可以向我解释为什么下面的代码不起作用吗?

我试图了解Java8的新功能并解决了BerlinClock Kata。在此期间,我不得不以"hh:mm:ss"格式解析字符串 - 我想使用流并编写以下代码。

import java.util.Arrays;

private Integer[] parseTime (String time){
    Integer[] hhmmss = (Integer[]) Arrays.stream(time.split(":"))
                                         .map(s->Integer.parseInt(s)).toArray();
    return hhmmss;
}

但运行时系统(我认为)抱怨显式类型转换(Integer[])无法完成。

据我了解,Arrays.stream(time.split(":"))部分返回Stream<String>,然后map(s->Integer.parseInt(s))将其转换为Stream<Integer>,然后toArray()生成Object[] }}。现在,由于中间流具有Integer[]类型参数,因此应该可以对Integer进行类型转换。

请注意,我知道如何在不使用

进行类型转换的情况下解决此问题
int[] hhmmss= Arrays.stream(time.split(":")
                    .mapToInt(Integer::parseInt).toArray();

并相应地将类型签名更改为int[] parseTime。 但我不明白为什么类型转换中存在问题。

1 个答案:

答案 0 :(得分:15)

对于第一种情况,Stream#map()方法会为您提供Stream<Integer>,然后Stream#toArray()会返回Object[],您需要将其转换为Integer[] 。但是在运行时,如果在内部创建Object[]而不是Integer[],则此强制转换可能会失败,这就是这里的情况。此流的toArray()方法的源代码如下所示:

@Override
public final Object[] toArray() {
    return toArray(Object[]::new);
}

并且您无法将Object[]转换为Integer[]引用。

您可以使用Stream#toArray(IntFunction)来解决此问题,然后您就不需要演员了:

private Integer[] parseTime (String time){
    Integer[] hhmmss = Arrays.stream(time.split(":"))
                    .map(s->Integer.valueOf(s))
                    .toArray(Integer[]::new);
    return hhmmss;
}

然而,在第二种情况下,Stream#mapToInt()方法会为您提供IntStream,而IntStream#toArray()会返回int[],因此不需要进行投射。