如何解决是如何决定谓词“和”方法在java中拥有消费者而不是生产者的?
我正在浏览 java 8 中引入的 Predicate 类,它是函数式接口。 Predicate类中有一个方法和方法,用于将多个谓词组合成一个。
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
我已经阅读了 Java 中 PECS 的概念,但仍然无法理解为什么在 Predicate 的情况下我们使用 ? super T
。 Java 程序员是如何决定它是消费者而不是生产者的。
我的意思是为什么不允许出现编译错误的行:
public class PredicateExample {
public static void main(String[] args) {
Predicate<Number> pred = n -> n.intValue() > 2;
Predicate<Integer> predInt = n -> n > 3;
//Compile error
//pred.and(predInt);
Predicate<Object> predObj = o -> Integer.parseInt(o.toString()) > 4;
pred.and(predObj); //Valid statement
Number n = new Integer(100);
System.out.println(pred.and(predObj).test(10));
System.out.println(predInt.and(pred).test(10));
//Compile error
//System.out.println(pred.and(predInt).test(10));
}
}
解决方法
Predicate<T>
接受 T
并给您一个 boolean
。是的,它是 boolean
的生产者,但这在这里并不重要。 在类型参数上应用 PECS 时,您应该考虑该类型是该类型参数的生产者还是消费者。
由于 Predicate<T>
接受 T
,它是 T
的消费者,因此 ? super
参数应该是 T
。
另一个例子:BiFunction<T,U,V>
接受一个T
和一个U
,并产生一个V
,所以它是T
的消费者,{{的消费者1}} 和 U
的生产者。因此,V
代表 ? super
和 T
,U
代表 ? extends
。如您所见,只有类型参数很重要。该类型可能会做的任何其他事情都不会。
如果你翻转两侧 - V
,这将创建一个 predInt.and(pred)
。
这是因为 Predicate<Integer>
被声明为产生与它被调用的谓词类型相同的谓词,所以 and
只能产生一个 pred.and(...)
,但一个 {{1} } 这里没有意义——另一个连接词只能接受整数!
您完全可以让它在两个订单中都能正常工作。如果您将 Predicate<Number>
声明为静态方法:
Predicate<Number>
然后你可以做这两个:
and
但是这样可读性较差:(
,Producer - 通过返回一个对象给你:T get()
对象必须是 T
或其子类,因此它是 extends
。
Consumer - 从您那里获取一个对象作为方法参数:void accept(T)
该方法可以采用更通用的类型,但不能要求更具体的类型,因此参数可以是super
。
由于 Predicate boolean test(T)
方法将对象作为参数,因此它是一个使用者。
参考:What is PECS (Producer Extends Consumer Super)?
,问题
Predicate<Number> pred = n -> n.intValue() > 2;
Predicate<Integer> predInt = n -> n > 3;
//Compile error
//pred.and(predInt);
是pred
接受Number
的所有子类(例如也Double
)但predInt
只接受一个特定的子类(Integer
)。
因此以下代码没问题:
Number n = Double.valueOf(100);
System.out.println(pred.test(n));
但是下面的代码(如果它可以编译)会在运行时失败:
Number n = Double.valueOf(100);
System.out.println(pred.and(predInt).test(n));
由于引入泛型正是为了防止此类运行时故障,因此它必须防止代码编译(即产生编译错误)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。