1 Functional programming
In mathematics, a function is a set of calculation plans with input and output quantities, that is, "what is used to do something." Relatively speaking, object-oriented overemphasizes "things must be done in the form of objects", while functional thinking tries to ignore the complex syntax of object-oriented - emphasizing what to do rather than the form in which to do it.
1.1 What to do, not how to do it
- For example:
new Thread(new Runnable(){ @Override public void run(){ //TODO things } }).start();
Regarding the usage Runnable
of anonymous inner classes, several points can be analyzed:
- The class
Thread
requiresRunnable
an interface as a parameter, and the abstract run method is the core used to specify the thread task content; - In order to specify the method body of run, we must create an implementation class of
Runnable
the interface ; - In order to save the trouble of defining an
Runnable
implementation class, we must use anonymous inner classes; - In the anonymous inner class, we must override and rewrite the abstract run method, so the method name, method parameters, and method return value have to be written again without errors;
- In fact , probably only the run() method body is the most important key in the program.
- What we really want to do is pass the code in the run method body to the Thread class and execute it.
think:
Do we really want to create an anonymous inner class object? No!
We just have to create an object in order to do this.
1.2 What is the essence of functional programming?
Passing a piece of code - this is our real purpose. Creating objects is just a method that has to be adopted due to object-oriented syntax. So, is there an easier way?
If we return our focus from "how to do" to the essence of "what to do", we will find that as long as the purpose can be better achieved, the process and form are not actually important.
One problem with anonymous inner classes is that even if the implementation of the anonymous inner class is very simple, such as an interface that only contains an abstract method, the syntax of the anonymous inner class still appears redundant.
Solution: You can use the lambda expression supported by JDK8. This expression is only implemented for an interface with an abstract method, and implements the interface function in the form of a concise expression as a method parameter.
new Thread(() -> System.out.println("Multi-threaded task execution!")).start();
The execution effect of this code is exactly the same as the one just now, and it can pass under compilation level 1.8 or higher. It can be seen from the semantics of the code: we start a thread, and the content of the thread task is specified in a more concise form.
There is no longer the shackles of "having to create interface objects", and there is no longer the burden of "abstract method overriding and rewriting", it's that simple!
1.3 Lambda expression
Basic syntax format of lambda expression
Arrows are used in statements to distinguish parameter lists and method bodies.
2 Functional interface
2.1 Is it possible to use lambdas instead of all anonymous inner classes?
Lambda expressions can be used instead of anonymous inner classes when there is only one abstract method in the interface. This is because lambda expressions are implemented based on functional interfaces.
The so-called functional interface refers to an interface with one and only one abstract method. Lambda expression is the embodiment of functional programming in Java. Only by ensuring that the interface has one and only one abstract method can lambda expression successfully deduce the implemented interface. method in.
2.2 Definition
In JDK8, the interface marked with the @FunctionalInterface annotation is a functional interface, and there is only one abstract method inside the functional interface.
Let’s take a look at the source code in the Runnable interface:
Note: The @FunctionalInterface annotation only explicitly marks the interface as a functional interface and forces the editor to perform stricter checks to ensure that the interface is a functional interface.
Some functional interfaces that existed before JDK8:
- java.lang.Runnable
- java.util.Comparater
- java.io.FileFilter
- java.lang.Reflect.InvocationHandler
Functional interface added in JDK8
The java.util.function package contains many classes to support functional programming in Java.
2.3 Simplification of Lambda expressions
The omitted writing method of lambda expression (further simplifying based on lambda expression)
1. If the method body code of the lambda expression has only one line of code, you can omit the curly braces and omit the semicolon!
2. If the method body code of the lambda expression has only one line of code, and if this line of code is a return statement, the return must be omitted and the semicolon must be omitted.
3. The parameter type can be omitted.
4. If there is only one parameter, the () outside the parameter can also be omitted.
In addition to the above simplification rules, lambda expressions can be further simplified using "method references".
public class TestOutter { public static void main(String[] args) { //Anonymous function writing method new Thread(new Runnable() { @Override public void run() { System.out.println("Thread 1 is started!") ; } }).start(); //lambda writing method new Thread(() -> {System.out.println("Thread 2 started!");}).start(); } }
3 method reference
Note : When the body of the lambda expression has only one statement, the program can not only omit the curly braces containing the body, but also reference methods and constructors (that is, construction methods) through the English double colon "::" syntax format.
Function : It can further simplify the writing of lambda expressions. Its essence is to directly reference the existing methods in the main part of the lambda expression. The main difference is the reference to ordinary methods and constructor methods.
3.1 Class name refers to static method
Definition: The class name refers to the static method, which is the reference to the static method through the class name. The class can be a special class that comes with Java, or it can be a custom ordinary class.
Example citations are as follows:
//Define functional interface @FunctionalInterface interface Calcable{ int calc(int num); } //Define a class and define a static method in the class class Math{ public static int abs(int num){ return num > 0 ? num : -num; } } public class Example { private static void printAbs(int num, Calcable calcable){ System.out.println(calcable.calc(num)); } public static void main(String[] args) { //1 , use anonymous inner class printAbs(-8, new Calcable() { @Override public int calc(int num) { return Math.abs(num); } }); //2. Use lambda expression printAbs(-8, (num) -> {return Math.abs(num);}); //3. Simplify lambda expression printAbs(-9, num -> Math.abs(num)); //4. Use method references to simplify lambda expressions printAbs(-7, Math::abs); } }
3.2 Object name reference method
Definition: The object name reference method refers to the reference to its method through the name of the instantiated object.
Example citations are as follows:
//Define functional interface @FunctionalInterface interface Utils{ String calc(String str); } //Define a class and define a common method in the class class UpperUtil{ public String toUpper(String str){ return str.toUpperCase(); } } public class Example2 { private static void printUpper(String ori, Utils u){ System.out.println(u.calc(ori)); } public static void main(String[] args) { UpperUtil upper = new UpperUtil() ; //1. Use anonymous inner class printUpper("abc", new Utils() { @Override public String calc(String ori) { return upper.toUpper(ori); } }); //2. Use lambda expression printUpper("bcd", (ori) -> {return upper.toUpper(ori);}); //3. Simplify lambda expression printUpper("cde", ori - > upper.toUpper(ori)); //4. Use method references to simplify lambda expressions printUpper("def", upper::toUpper); } }
3.3 Constructor reference method
Definition: refers to a reference to the constructor that comes with the class.
Example citations are as follows:
//Define functional interface @FunctionalInterface interface PersonBuilder{ Person buildPerson(String name); } //Define a class, define a constructor and common methods in the class class Person{ private String name; public Person(String name){ this. name = name; } public String getName(){ return name; } } public class Example3 { private static void printName(String name, PersonBuilder buildPerson){ System.out.println(buildPerson.buildPerson(name).getName()); } public static void main(String[] args) { //1. Use lambda expression printName("李思", (String name) -> {return new Person(name);}); //2. Use the constructor reference method printName("Zhang San", Person::new); } }
3.4 Class names refer to common methods
Definition: refers to a reference to a common method of a common class through its class name.
Example citations are as follows:
//Define functional interface @FunctionalInterface interface Printable{ void print(StringUtils su, String str); } //Define a class and method class StringUtils{ public void printUppercase(String str){ System.out.println(str.toUpperCase( )); } } public class Example4 { private static void printUpper(StringUtils su, String str, Printable printable){ printable.print(su, str); } public static void main(String[] args) { //1. Use Anonymous inner class printUpper(new StringUtils(), "abc", new Printable() { @Override public void print(StringUtils su, String str) { su.printUppercase(str); } }); //2. Use lambda expression printUpper(new StringUtils(), "bcd", (Object, t) -> Object.printUppercase(t)); //3. Use method reference Method printUpper(new StringUtils(), "def", StringUtils::printUppercase); } }