While reading the Stream
interface source code I found this method signature:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
I wonder why the input type of mapper
is ? super T
? super T
while the output type is ? extends R
? extends R
, why not use ? extends
? extends
for both?
Consider you want to map a CharSequence
to another CharSequence
(thus T = R = CharSequence
). Which functions will work for you?
Function<Object, String> fn1 = Object::toString;
Is it good for you? Yes, because it can take any CharSequence
(which is also Object
) and convert it to the String
(which is also CharSequence
).
Function<CharSequence, StringBuilder> fn2 = StringBuilder::new;
Is it good for you? Yes, because it can take any CharSequence
and convert it to the StringBuilder
(which is also CharSequence
).
Function<String, String> fn3 = String::trim;
Is it good for you? No, because it cannot take any CharSequence
, only some of them.
Thus you can see that first type argument must be CharSequence
or any superclass, but second must be CharSequence
or any subclass.
Because of PECS :) - Producer Extends, Consumer Super
Producer Extends - If you need a List to produce T
values (you want to read Ts from the list), you need to declare it with ? extends T
? extends T
Consumer Super - If you need a List to consume T
values (you want to write Ts into the list), you need to declare it with ? super T
? super T
There is a rule of thumb which was first mentionned by Joshua Bloch in his Effective Java book which stands as PECS .
This function produce a result (? extends R)
from what it received ( ? super T
).
The documentation of java.util.Function
is kinda clear on that :
Represents a function that accepts one argument and produces a result.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.