3

This is the class definition of CompletionStage

public interface CompletionStage<T> {
...
}

And this is the method thenApply

public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);

My questions is: Why is it taking ? super T as the first argument of Function... shouldn't it be ? extends T since any subClass of T can be cast as T ? And any super class of T cannot be cast as T ??

user207421
  • 305,947
  • 44
  • 307
  • 483
user3385957
  • 131
  • 2
  • 8
  • `fn` *consumes* the result of the stage. As such, it can be a function which accepts T or any supertype of T, since then any T it receives is also an instance of that supertype. It can't require a *subtype* of T, because there is no guarantee that the result of the stage will be of that specific type. – Andy Turner Feb 18 '18 at 20:51
  • Stupid title. I fixed it for your. – user207421 Feb 19 '18 at 00:38

1 Answers1

2

I'd approach this by asking, which signature would make most sense? There are three options:

  • Function<? extends T, ? extends U>
  • Function<T, ? extends U>
  • Function<? super T, ? extends U>

First of all, ? extends T does not include T. So you could not pass Function<T, U> to CompletionStage<T> which would have been unexpected. So ? extends T is not the best choice.

This leaves us with simply T or ? super T.

Simply T would work for Function<T, U>, just as ? super T. But which is better? ? super T would allow you to apply functions with arguments which are T or superclasses of T. This is much more flexible compared to simply T since you could use more generic functions. For instance, you could do CompletionStage<Integer>.thenApply(Function<Number, String>) which would not be possible with simple T. ? super T also does not seem to have any drawbacks, at least I don't see any.

So from my point of view, ? super T is clearly a better choice.

lexicore
  • 42,748
  • 17
  • 132
  • 221