eclipse 此表达式的目标类型必须是函数式接口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27771488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The target type of this expression must be a functional interface
提问by user2336315
I created a function to filter with multiple predicates for which I perform a logical AND for them:
我创建了一个函数来过滤多个谓词,我对它们执行逻辑 AND 运算:
@SafeVarargs
public static <T> Stream<T> filter(Stream<T> source, Predicate<T>... predicates) {
return source.filter(Arrays.stream(predicates).reduce(predicates[0], Predicate::and));
}
When calling:
调用时:
filter(IntStream.range(0, 10).boxed(), x -> x % 2 != 0, x -> x%3 == 0).forEach(System.out::println);
It works fine and prints 3 and 9. However when I pass a single predicate such as:
它工作正常并打印 3 和 9。但是,当我传递一个谓词时,例如:
filter(IntStream.range(0, 10).boxed(), x -> x % 2 != 0).forEach(System.out::println);
I get a compilation error:
我收到一个编译错误:
The target type of this expression must be a functional interface
Why is this?
为什么是这样?
For infos I use Eclipse Luna version 1.
对于信息,我使用 Eclipse Luna 版本 1。
采纳答案by Holger
This is a corner case for the compiler. In order to determine whether it should apply varargs wrapping of arguments into an array or simply pass an array, it needs to know the type of the last argument, however, in the case of a lambda expression it needs the invoked method signature to determine the type. But it's clear what should happen as a lambda expression can never be an array type and so, javac
compiles it without problems.
这是编译器的一个极端情况。为了确定它是否应该将参数的可变参数包装应用到数组中或简单地传递一个数组,它需要知道最后一个参数的类型,但是,在 lambda 表达式的情况下,它需要调用的方法签名来确定类型。但是很明显,当 lambda 表达式永远不能是数组类型时应该发生什么,因此javac
编译它没有问题。
One acceptable work-around would be to overload the method:
一种可接受的解决方法是重载该方法:
@SafeVarargs
public static <T> Stream<T> filter(Stream<T> source, Predicate<T>... predicates) {
return source.filter(
Arrays.stream(predicates).reduce(predicates[0], Predicate::and));
}
public static <T> Stream<T> filter(Stream<T> source, Predicate<T> predicate) {
return source.filter(predicate);
}
This would be an an acceptable work-around as it does not require any changes on the calling side while improving the efficiency for the single-arg case at the same time.
这将是一种可接受的变通方法,因为它不需要在调用方进行任何更改,同时提高单参数情况的效率。
Please note that your varargs method allows zero arguments but will fail if called that way. So you should either, add another overload:
请注意,您的 varargs 方法允许零参数,但如果以这种方式调用将失败。所以你应该添加另一个重载:
public static <T> Stream<T> filter(Stream<T> source) {
return source;
}
or make the method safe for the zero argument case:
或使该方法对于零参数情况是安全的:
@SafeVarargs
public static <T> Stream<T> filter(Stream<T> source, Predicate<T>... predicates) {
return Arrays.stream(predicates).reduce(Predicate::and)
.map(source::filter).orElse(source);
}
回答by sprinter
Both Netbeans and Eclipse have a number of bugs in the area of parsing lambda expressions in Java. They are slowly getting fixed but, until they are, the best workarounds I have found are: 1. declare types 2. if that doesn't work, use a block 3. if that doesn't work, create an anonymous object that implements the predicate/function etc.
Netbeans 和 Eclipse 在解析 Java 中的 lambda 表达式方面都有许多错误。它们正在慢慢修复,但在它们修复之前,我发现的最佳解决方法是: 1. 声明类型 2. 如果这不起作用,请使用块 3. 如果这不起作用,请创建一个匿名对象来实现谓词/函数等。
These make your code messier but they are necessary in a number of situations.
这些使您的代码更加混乱,但在许多情况下它们是必要的。
回答by Peteter
Sometimes Eclipse needs a good ol' clean and rebuild of all projects and the problem goes away.
有时 Eclipse 需要对所有项目进行良好的清理和重建,问题就会消失。