在阅读Stream
接口源代码时,我发现了这个方法签名:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
我想知道为什么mapper
的输入类型为? super T
而输出类型为? extends R
,为什么不对? extends
使用user.id
?
答案 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 book中PECS首先提到了一个经验法则,其中java.util.Function
代表SAC #37858。
此函数根据收到的结果((? extends R)
)生成结果? super T
。
context.xml file configured against spring security的文档有点清楚:
表示接受一个参数并生成结果的函数。