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
while the output type is ? extends R
, why not use ? extends
for both?
In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).
If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class. These are known as bounded-types in generics in Java.
What is the difference between a wildcard bound and a type parameter bound? A wildcard can have only one bound, while a type parameter can have several bounds. A wildcard can have a lower or an upper bound, while there is no such thing as a lower bound for a type parameter.
Use an upper-bounded wild card only when values are to be retrieved and processed and the data structure (ArrayList) won't be changed. This means that the corresponding argument of a call on m2 can be an ArrayList whose elements are of any class that is Integer or a superclass of Integer, including Number and Object.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With