2

I was looking at Java8's functional Interface Consumer. I can see a default method andThen. I understood that the method is used to chain consumer's together. Below is the code of andThen method:

default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
}

Question: Why only the type & SuperType of element (? super T) are allowed in the Consumer argument of andThen method. I want to understand the purpose of the usage here.

I would help me in improving my understanding of Generics.

Sahil Gupta
  • 121
  • 1
  • 7
  • I understood "What is PECS (Producer Extends Consumer Super)?" . What i asked here is what is the purpose of using " super T>" in andThen here. Why to add restrictions to allow only the type and superType in the Consumer of andThen. – Sahil Gupta Jan 14 '19 at 05:29
  • So you are saying this is not a duplicate. OK, I thought you were asking about that, but it seems you want to know about this specific case. Reopened. Let's see what others have to say. – fps Jan 15 '19 at 02:24
  • 1
    In short, the lower bound is there to allow a consumer of more general objects. Consider i.e. a consumer that adds an element to a `List`. This could be i.e. `Consumer ci = list::add;`. Now, besides adding that element to the list, you might also want to print that element to the screen. If you happen to have that second consumer already defined i.e. `Consumer co = System.out::println;`, you wouldn't be able to chain both consumers by using `Consumer.andThen` if `Consumer.andThen` accepted just a `Consumer`, because `co` is not a `Consumer` (as `ci`). – fps Jan 15 '19 at 02:33
  • Thanks Federico !! I got confused but understood now. – Sahil Gupta Jan 15 '19 at 09:12

1 Answers1

3

Let's say you have a Consumer<Dog> and a Consumer<Animal>. Of course, you can pass a Dog into either of these accept methods, as a Dog is an Animal.

However, in Java, there is no inheritance relationship between Consumer<Dog> and Consumer<Animal>, for reasons that have been discussed on other questions on this site. So to allow us to chain any other Consumer that will accept a Dog, we need to declare it as a Consumer<? super Dog>.

Joe C
  • 15,324
  • 8
  • 38
  • 50
  • But why not use "andThen(Consumer after)" or "andThen(Consumer extends T> after)" here ? I am trying to understand things here. – Sahil Gupta Jan 14 '19 at 05:34
  • 1
    @SahilGupta `andThen(Consumer after)` would forbid to chain a `Consumer ca` after a `Consumer cd`: `cd.andThen(ca)` - but a `Consumer` is a valid consumer for all `Dog`s. `andThen(Consumer extends T> after)` would allow `ca.andThen(cd)`. But what if the element that is fed into `ca` is a `Cat`? You would then feed the `Cat` into the `Consumer` – Thomas Kläger Jan 14 '19 at 06:22
  • @ThomasKläger : Thanks. That answers my question :) – Sahil Gupta Jan 15 '19 at 09:16