此表达式的目标类型必须是功能界面 [英] The target type of this expression must be a functional interface

查看:156
本文介绍了此表达式的目标类型必须是功能界面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个函数来过滤多个谓词,为它们执行逻辑AND:

I created a function to filter with multiple predicates for which I perform a logical AND for them:

@SafeVarargs
public static <T> Stream<T> filter(Stream<T> source, Predicate<T>... predicates) {
    return source.filter(Arrays.stream(predicates).reduce(predicates[0], Predicate::and));
}  

拨打电话时:

filter(IntStream.range(0, 10).boxed(), x -> x % 2 != 0, x -> x%3 == 0).forEach(System.out::println);

它工作正常,打印3和9.但是当我传递单个谓词如: p>

It works fine and prints 3 and 9. However when I pass a single predicate such as:

filter(IntStream.range(0, 10).boxed(), x -> x % 2 != 0).forEach(System.out::println);

我收到一个编译错误:

The target type of this expression must be a functional interface

为什么这是吗?


对于信息,我使用Eclipse Luna版本1。

For infos I use Eclipse Luna version 1.

推荐答案

这是编译器的一个角落。为了确定是否应用将参数包装到数组中或简单地传递数组,它需要知道最后一个参数的类型,然而,在lambda表达式的情况下,它需要调用方法签名来确定类型。但是很明显,应该发生什么,因为lambda表达式永远不会是数组类型,所以 javac 编译没有问题。

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.

一个可以接受的解决办法是超载方法:

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.

请注意,您的varargs方法允许零参数,但如果以这种方式调用将失败。所以你应该添加另一个重载:

Please note that your varargs method allows zero arguments but will fail if called that way. So you should either, add another overload:

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);
}

这篇关于此表达式的目标类型必须是功能界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆