Monday, November 8, 2021

Quiz yourself: Java andThen methods for consumers and functions

Oracle Java Exam Prep, Oracle Java Preparation, Oracle Java Certification, Oracle Java Career, Oracle Java Jobs

In Java, a Consumer method’s role is to execute a side effect such as printing to the console, logging an event, or writing to a database.


Given the following two classes

import java.util.function.Consumer;
import java.util.function.Function;
class Value {
  static Integer counterC = 1;
  static Integer counterF = 1;
}
public class ChainTest {
  public static void main(String[] args) {
    Consumer<Integer> addC = i -> Value.counterC += i;
    Consumer<Integer> showC = i -> System.out.print(i);
    addC.andThen(showC).accept(1);

    Function<Integer, Integer> addF = i -> Value.counterF += i;
    Function<Integer, Integer> showF = i -> {
      System.out.print(i); return i;
    };
    addF.andThen(showF).apply(1);
  }
}

A. 11
B. 12
C. 21
D. 22
E. There is no output.

Answer. This quiz question demonstrates aspects of the java.util.function.Consumer and java.util.function.Function interfaces, and the use of the andThen methods of each.

Let’s start with the Consumer example. The abstract method declared in a Consumer has a void return type, so it cannot return a value. Rather, the method’s role is to execute a side effect such as printing to the console, logging an event, or writing to a database.

The andThen method chains two consumers. After addC is invoked, counter refers to an integer with the value 2, so it’s tempting to think that showC might print 2. However, the second consumer is invoked with the original object that was passed to the first consumer.

Looking at how the Java API implements the method helps reinforce this understanding. Here’s the code.

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

The two calls to accept are both invoked with the same argument t (which is the immutable wrapper Integer(1)) passed sequentially to the first consumer and then to the second consumer.

It’s important to notice that the expression passed to the accept method is a literal 1, and while this will be autoboxed to an Integer, it is that object—not the object referred to by counter—that is passed to both of the consumers.

From this you can see that the first digit printed will be 1. Therefore, options C, D, and E are incorrect.

Now look at the second part of the code, which chains two Function objects. The andThen method of the Function interface passes the value returned by the first function as the argument to the second function. Here is how the Java API implements this method.

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
  Objects.requireNonNull(after);
  return (T t) -> after.apply(apply(t));
}

Oracle Java Exam Prep, Oracle Java Preparation, Oracle Java Certification, Oracle Java Career, Oracle Java Jobs
Notice that the argument to the invocation of after.apply is the value returned from the first apply invocation. In the example in the question, the addF method actually returns the reference to the Integer(2) object that’s assigned to counter. (Recall that assignments in Java form an expression that has the value that is being assigned.) Thus, Integer(2) will be the value passed to showF, which consequently prints 2 to the console. Therefore, option B is the correct answer.

By the way, showF and the entire expression addF.andThen(showF).apply(1) also return the value Integer(2); however, this value is abandoned.

Conclusion. The correct answer is option B.

Source: oracle.com

Related Posts

0 comments:

Post a Comment