【问题标题】:Predicate interface in Java8Java 8 中的谓词接口
【发布时间】:2017-03-14 06:55:27
【问题描述】:

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

【问题讨论】:

标签: generics java-8 predicate


【解决方案1】:

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

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&lt;Long&gt; 呢? Long,但是如果它指向MyPredicate&lt;Integer&gt;呢?

因此,在这种情况下,除了 null 之外,没有其他方法可以将 p1 应用于任何内容。

介绍一下p2

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

由于它使用super,我们甚至不能这样做:

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

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

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

会编译得很好;因为我们 100% 确定无论是什么类型,它都是 Number 的超级类型

我们换个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
    }
}

【讨论】:

  • Eugene,现在我明白为什么使用扩展没有帮助了。对您的解释的一个小修正。 ? super Number 可以采用任何超类型的 Number。在您提到的上述解释中,将保证扩展不正确的 Number。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多