流在没有过滤器(谓词)的情况下工作,使用它"Incompatible types"



为什么只有当过滤器谓词行被注释掉时,下面的代码才能工作?对于过滤器行,它给了我这个错误:

Incompatible types: java.lang.Object cannot be converted to java.lang.String

我做错了什么?

import static java.util.stream.Collectors.joining;
import java.util.Arrays;
import java.util.function.Predicate;
import java.util.regex.Pattern;
public class PredicateStreamInvalidType {
   public static void main(String[] ignored) {
      String input = "one two three four five six seven eight";
      Predicate containsAnE = Pattern.compile("e").asPredicate();
      String[] splits = input.split(" ");
      String output = Arrays.stream(splits).
            //filter(containsAnE).
            collect(joining(" "));
      System.out.println(output);
   }
}

我期待这样的输出:

one three five seven eight

您正在使用Predicate<T>的原始形式-使用原始类型通常会导致涉及Object的编译时错误,而您期望使用更具体的类型。

你所需要做的就是改变containsAnE的编译时类型:

Predicate<String> containsAnE = Pattern.compile("e").asPredicate();

Pattern.asPredicate被声明为返回Predicate<String>,所以你应该很好去:)

作为帮助您避免将来出现此类问题的一种方法,您应该查看是否可以在使用原始类型时获得您正在使用的任何环境(IDE,命令行编译等)的警告。总是一个坏主意。

Arrays.stream(splits)返回Stream<String>

Stream<String>.filter方法有签名

    Stream<String> filter(Predicate<? super String> predicate)

通过未检查的转换适用于参数containsAnE,它是原始的Predicate。现在发生了一件有趣的事情—由于未检查的转换,返回类型被擦除!参见这个问题

因此filter(containsAnE)返回原始Stream

原始类型的实例方法也都被擦除,因此collect方法签名是

    Object collect(Collector collector)

这可以通过对Collector<CharSequence, ?, String>参数joining(" ")的子类型来应用。代码到目前为止已经编译好了。但是返回类型是Object

如果您将output变量的类型更改为Object

    Object output = Arrays.stream(splits)
        .filter(containsAnE)
        .collect(joining(" "));

代码编译,并运行…正确。

这不是意外;为了确保前泛型代码能够与新的泛型api一起工作,我们做了很多努力。这在2005年非常重要。当然,今天,我们不再有这样的担忧。就是不要使用原始类型。(除非我们不得不……)

相关内容

最新更新