函数输入类型

时间:2015-08-21 11:35:10

标签: java generics java-8

在阅读Stream接口源代码时,我发现了这个方法签名:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

我想知道为什么mapper的输入类型为? super T而输出类型为? extends R,为什么不对? extends使用user.id

3 个答案:

答案 0 :(得分:19)

考虑您要将CharSequence映射到另一个CharSequence(因此T = R = CharSequence)。哪些功能适合您?

Function<Object, String> fn1 = Object::toString;

对你有好处吗?是的,因为它可以任何 CharSequence(也是Object)并将其转换为String(也是CharSequence)。

Function<CharSequence, StringBuilder> fn2 = StringBuilder::new;

对你有好处吗?是的,因为它可以任何 CharSequence并将其转换为StringBuilder(也是CharSequence)。

Function<String, String> fn3 = String::trim;

对你有好处吗?不,因为它不能任何 CharSequence,只能使用其中的一部分。

因此,您可以看到第一个类型参数必须是CharSequence或任何超类,但第二个必须是CharSequence或任何子类。

答案 1 :(得分:12)

由于PECS :) - Producer Extends,Consumer Super

生产者扩展 - 如果您需要List来生成T值(您希望从列表中读取Ts),则需要使用? extends T

消费者超级 - 如果您需要使用List来使用T值(您希望将Ts写入列表),则需要使用? super T

答案 2 :(得分:10)

Joshua Bloch Effective Java bookPECS首先提到了一个经验法则,其中java.util.Function代表SAC #37858

  • PE Producer扩展
  • CS Consumer super

此函数根据收到的结果((? extends R))生成结果? super T

context.xml file configured against spring security的文档有点清楚:

  

表示接受一个参数并生成结果的函数。