0

The signature of andThen is: (Function<? super R,? extends V> after)

I cannot understand why the input of the function is : ? super R

In my understanding, super is used when we are writing a value. But the function passed to andThen will read the value of first function.

For ex:

Function<Integer, Integer> f1 = x -> x * 2;
Function<Integer, Integer> f2 = x -> x * 3;
Integer myApplyThen = (input) -> {
    Integer y1 = f1.apply(input);
    Integer y2 = f2.apply(y1);
    return y2;
}

As we can see in this logic that there is no need to write any value to the generic parameters passed to Function. Both f1.apply and f2.apply are just transforming their inputs i.e reading and returning. So according to me, the type definition of andThen should have been: Function<? extends R,? extends V> after

But since this is not the case, what am I missing?

conquester
  • 1,082
  • 2
  • 21
  • 44

1 Answers1

2

The reason isn’t obvious when you use Integer, which is a final class and therefore cannot have a subclass.

Consider this:

Function<Number, Number> f1 = x -> x.doubleValue() * 2;
Function<Double, Double> f2 = x -> x.doubleValue() * 3;

Number myApplyThen = (input) -> {
    Number y1 = f1.apply(input);
    Double y2 = f2.apply(y1);    // ERROR: f2 requires a Double!
};

The function given to andThen needs to be capable of handling the result type, R. If it accepts a supertype, then we know it can handle R as input; for example, a Function<Object, String> will accept any value as input.

But if the function given to andThen only accepts a subset of R, which is what ? extends R (potentially) signifies, then it is not safe to assume you can pass any R instance to it.

We can see this in the above example: f2 expects a particular subtype of Number as input, and since the compiler only knows that f1 is capable of returning a Number object, which might be a Double or Integer or BigDecimal or AtomicLong, it is not safe to pass that result as input to f2.

VGR
  • 40,506
  • 4
  • 48
  • 63