为什么Java 8的谓词<T>扩展了Function<T,Boolean>

如果我编写接口,我想在接口中编码它只是一个返回基元的函数,如下所示:Predicateboolean

@FunctionalInterface
public interface Predicate<T> extends Function<T, Boolean> {

    boolean test(T t);

    @Override
    default Boolean apply(T t) {
        return Boolean.valueOf(test(t));
    }
}

我想知道,Java 8 API设计人员选择将完全分开的原因是什么?有没有证据表明他们考虑这样做并决定反对?我想类似的问题也适用于所有其他“特殊”功能接口,如(可能是),()和原始函数,如()。PredicateFunctionConsumerFunction<T, Void>SupplierFunction<Void, T>IntFunctionFunction<Integer, T>

我还没有非常深入和彻底地思考过这个问题的所有后果,所以我可能错过了一些东西。

编辑:一些答案强调了应用和测试之间的语义区别。我并不是说我不欣赏这种区别,我同意这种区别是有益的。我不明白的是,为什么 a 仍然不是同一种方式,例如,a 是 a or 是 a ,这是一个 .PredicateFunction inListCollectionDoubleNumberObject

如果(以及所有其他特殊的通用功能接口,例如,等)与 有这种关系,它将允许人们在预期参数的地方使用它(想到的是与其他函数的组合,例如调用或避免在API中编写几个专用函数,当如上所述的自动(取消)装箱实现就足够了时)PredicateConsumerSupplierIntUnaryOperatorFunctionFunctionmyFunction.compose(myPredicate)

编辑2:在openjdk lambda项目中,我发现原始的功能接口曾经扩展到Brian Goetz在2012-12-19的这个提交之前。我无法在当时的任何lambda-dev或JSR专家组邮件列表中找到更改的具体原因。Function


答案 1

中的方法返回 。中的方法返回 。他们是不一样的。虽然有自动装箱,但Java方法不使用包装类,而基元会这样做。此外,还有差异,例如可以趁不能。Predicate<T>booleanFunction<T, Boolean>BooleanBooleannullboolean

在 .中的方法具有返回类型,这意味着它可以隐式返回或返回 using ,但 in 中的方法必须显式返回。Consumer<T>Consumer<T>voidreturn;Function<T, Void>return null;


答案 2

不需要这种可疑的继承层次结构。这些功能接口是可互换的。

Function<A,Boolean> f1=…;
Predicate<A>        p1=…;

Predicate<A>        p2=f1::apply;
Function<A,Boolean> f2=p1::test;

这在两个方向上都有效。那么,为什么要有一个继承关系来宣传一个特定的方向呢?