Java8中的谓词接口

时间:2017-03-14 06:55:28

标签: generics java-8 predicate

Java 8中的Predicate接口的

and()or()方法采用T的任何超类型,即? super T而不是? extends T。我期待它采用任何扩展T的类型。我这样思考的动机是,由于T是我定义谓词的类型,复合谓词也应该在T上(即T的任何子类型)。成为? super T背后的原因是什么?有人可以帮我理解吗?

1 个答案:

答案 0 :(得分:2)

所以这是我对它的理解。假设我们有这个:

interface MyPredicate<T> {
    boolean test(T t);
}

这些声明:

 MyPredicate<? extends Number> p1 = (Number n) -> n.intValue() > 9;
 MyPredicate<Integer> p3 = null;
 MyPredicate<Long> p4 = null;

由于IntegerLongNumber的子类型,我们可以这样做:

p1 = p3;
p1 = p4;

同时,我们假设p3p4不为空。他们在测试中可以接受的唯一类型是IntegerLong

p3.test(12);
p4.test(12L);

p1会接受什么? Integer,但如果它指向MyPredicate<Long>怎么办? Long,但如果它指向MyPredicate<Integer>怎么办?

因此在这种情况下除了null之外没有办法将p1应用于任何东西。

我们来介绍p2

MyPredicate<? super Number> p2 = (Number n) -> n.intValue() > 10;

由于它使用super,我们甚至无法做到这一点:

p2 = p3; // will not compile
p2 = p4; // will not compile

但这一次我们知道我们会有一些类型Number因为它是超类型,所以我们可以在这里安全地应用数字。含义:

p2.test(12); // 12 is Number

编译得很好;因为我们100%确定无论哪种类型,它都是数字的超级类型

让我们改变MyPredicate

    interface MyPredicate<T> {

    boolean test(T t);

    default MyPredicate<T> and(MyPredicate<? extends T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t); // this will not compile
    }
}

因为我们使用了extends,所以我们不知道实际的类型,因此它会失败,与super不同:

    interface MyPredicate<T> {

    boolean test(T t);

    default MyPredicate<T> and(MyPredicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t); // compiles just file
    }
}