为什么只有当过滤器谓词行被注释掉时,下面的代码才能工作?对于过滤器行,它给了我这个错误:
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年非常重要。当然,今天,我们不再有这样的担忧。就是不要使用原始类型。(除非我们不得不……)