The usage of lower bound in collections context is more or less clear to me (see PECS question). Not so with functional interfaces in Java. E.g. Why Optional.map method has the signature with lower type bound:
<U> Optional<U> map(Function<? super T, ? extends U> mapper);
What is the advantage of using super here and why the code below does not compile?
public static void main(String[] args) {
Function<? super BigDecimal, ? extends Number> mapper = dec -> dec
.divide(BigDecimal.TEN)
.doubleValue();
BigDecimal bigD = BigDecimal.ONE;
//works
Optional.of(bigD).map(mapper);
Number number = BigDecimal.ONE;
// the following does not compile,
// despite Number is super type of BigDecimal
Optional.of(number).map(mapper);
}
The purpose of the lower bound in the mapper
parameter to map
is to expand the range of acceptable Function
s, to include not just those Function
s that have exactly T
, but also those types of which T
might be a subclass. E.g. such an Optional<BigDecimal>
may accept not just a Function<BigDecimal, Number>
, but a Function<Number, Number>
, because a BigDecimal
is a Number
. Such a function should be able to operate on a BigDecimal
because it takes a Number
.
Your line Optional.of(number).map(mapper);
doesn't compile because here T
is Number
, not BigDecimal
. Attempting to pass in a Function
whose T
is BigDecimal
doesn't match the signature -- BigDecimal
is not a supertype of Number
. Your attempt to take advantage of ? super T
here fails because you've used a different T
, not because it failed ? super T
somehow. Those are two different concepts.