简体   繁体   中英

Java Consumer Interface

someone can help me understand below code from Java 8 Functional Interface As per my understanding accept() takes as input and process it but does not return any value then in case of andThen() how it works

accept() method takes as input the type T and returns no value.

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

In order to understand what is getting return ed from that API, you can try visualizing the implementation as :

default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return new Consumer<T>() { // return the complete Consumer implementation
        @Override
        public void accept(T t) {
            Consumer.this.accept(t); // accept current consumer
            after.accept(t); // and then accept the 'after' one.
        }
    };
}

and now relate that

(T t) -> { accept(t); after.accept(t); } 

is a Consumer returned which ensures that the current one is accept ed first and then the one mentioned as after .

A functional interface must have only one abstract method. However, it can have as many static and default methods as you'd like. The methods of Consumer are:

  1. accept(T)

    • This is the single abstract method of Consumer . It accepts a single generic argument of type T and returns nothing (ie void ). This is the method that's implemented by a lambda expression or method reference.
  2. andThen(Consumer)

    • This is a default method. In other words, it has an implementation and is thus non-abstract. The method accepts a Consumer and returns another Consumer . Since it's a default method, the single abstract method of Consumer remains accept(T) .

The above explains why Consumer can have a method that returns something other than void . Now, when it comes to the implementation of andThen , it's important to realize there are actually three Consumer s involved:

  1. The instance on which andThen was invoked.
  2. The instance referenced by after .
  3. The instance returned to the caller.

If you format the code so not everything is on the same line it may be easier to follow:

default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    // Returns Consumer instance #3. The lambda is the implementation
    // of the 'accept' method.
    return (T t) -> {
        accept(t);       // Invokes 'accept' on Consumer instance #1.
        after.accept(t); // Invokes 'accept' on Consumer instance #2.
    }
}

I think I understand your concern. You wonder why could you call andThen() after accept() if accept() returns void.

The thing is, that you first define a Consumer object, and on that instance you call andThen() method. For example:

Consumer<String> consumer = s -> System.out.println(s);
consumer.andThen(s -> System.out.println(s.toUpperCase()));        

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM