Below we continue to dive into the Java8 functional programming model
public class Test1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); list.forEach(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer); } }); }}This program is simple, first initialize a collection of Integer type and then output each element to the console. Among them, we noticed the forEach method, which is the newly added default method in Java 8.
public interface Iterable<T> { . . omit. default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }}It is declared in the Iterable interface and is modified by the keyword default. In this way, any subtype of this interface can inherit the implementation of the forEach method, so the List interface is an indirect subinterface of Iterable, so it also inherits the default method. Java8 adopts this clever way to extend the functions of the interface and is compatible with the old version.
Next, we analyze the implementation of forEach. First, we receive a parameter action of Consumer type, perform non-empty judgment, and then traverse all current elements and hand them over to the action's accept method for processing. So what the hell is Consumer? Look at the source code
@FunctionalInterfacepublic interface Consumer<T> { /** * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); . .Omitted.} An interface, with only one abstract method, is modified by @FunctionalInterface, a typical functional interface.
OK, now we know that the parameter of the Consumer type received by forEach is a functional interface. The only accept abstract method in the interface receives a parameter and does not return a value. From the previous article, we know that one of the ways to create instances of functional interface types is to use Lambda expressions, so you can transform the top program.
public class Test1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); //Lambda expression receives a parameter without returning the value list.forEach(item -> System.out.println(item)); }} The lambda expression item -> System.out.println(item) receives a parameter without returning a value, and meets the acceptance method signature requirements and is compiled and passed.
That is to say, if a lambda expression is used to create a functional interface instance, the entry parameters and return of this lambda expression must conform to the method signature of the only abstract method in this functional interface.
Next, the program will be modified
public class Test1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); //Method reference list.forEach(System.out::println); }} I saw two colons behind out, but I was in a mess anyway. . . This is the second way to create a functional interface instance: method reference method reference syntax is object:: method name
Similarly, using method reference method to create functional interface instances must also comply with the definition of method signature. See the println method source code here
public void println(Object x) { String s = String.valueOf(x); synchronized (this) { print(s); newLine(); }} Receive a parameter and does not return the value, and compile it through.
Finally, let’s take a look at the last type of creating a functional interface. The third method: construct method reference and continue to modify the program.
public class Test1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); //Constructor method reference list.forEach(Test1::new); } Test1(Integer i){ System.out.println(i); }} The syntax referenced by the constructor is: class name::new
We have added a new constructor to Test1, which receives a parameter, does not return a value, and compiles through. (To show the usage of constructor citations only)
Based on the previous article, we can summarize three ways to create functional interface types:
1. lambda expression
2. Method citation
3. Constructor method reference
Note: No matter which method, the method signature must be in line with the abstract method.