Search code examples
javagenericsjava-8option-typebounded-wildcard

Why lower bound is used in functional interfaces


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);
}

Solution

  • The purpose of the lower bound in the mapper parameter to map is to expand the range of acceptable Functions, to include not just those Functions 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.