My last article introduced functional interfaces and Lambda expressions, as well as Java solutions to so-called closures. Let’s go deeper this time.

0x00 Functional interface

I talked a little bit about functional interfaces, but maybe I just gave you a general idea, what is a functional interface

  • A functional interface is an interface with an abstract method in it and nothing else.
  • FunctionalInterface annotations annotate a FunctionalInterfaceclass.methods.The enumeration.attributeThese.
  • If the interface is annotated@FunctionalInterface, the class must conform to the functional interface specification
  • Even if an interface has no annotation@FunctionalInterfaceIf the interface meets the functional interface rules, it is still considered a functional interface.

This time let’s take a closer look at functional interfaces in code





Demo01

As shown above, the most common functional interface is one that contains only one abstract method





Two abstract methods, error

Also, when an interface has two abstract methods, it is no longer a FunctionalInterface, and the @functionalinterface annotation will generate an error when compiled





Special case – 01

Oddly enough, there are three abstract methods, so why not report an error? Object is the default parent of all classes. This means that any Object contains the methods in Object, even the implementation of a functional interface has the default methods in Object. Methods overwritten in Object are not included in interface methods, except for final methods. Methods that can be overwritten in Object are written to the interface without affecting the characteristics of functional interfaces





Special case.

Java8 allows interfaces to have non-abstract methods that use the default modifier in the interface and are called default methods. Default methods also do not affect the nature of functional interfaces. We can still think of DemoConsumer as a functional interface.

The 0x01 Lambda expression goes deep

Lambda expressions are of the following form

(Param1, param2, param3, param4...) - > {doing... };Copy the code

This leads to a variety of ways to write:

 / / 1.
() -> System.out.println("Hello Lambda");
/ / 2.
number1 -> int a = number1 * 2;
/ / 3.
(number1, number2) -> int a = number1 + number2;
/ / 4.
(number1, number2) -> {
  int a = number1 + number2;
  System.out.println(a);
}Copy the code

Let’s take a closer look at Lambda expressions by refactoring some code

public class FunctionalInterfaceTest {
    public static void main(String[] args) {
        List<String> demoList = Arrays.asList( "Zing"."Three"."Xiao Ming"."Little red"."Zhao Ritian");
       rollCall(demoList);
    }
    public static void rollCall(List<? extends String> list){
        for(String name : list){
            if(name.startsWith("Small")){
                System.out.println(name); }}}}Copy the code

If you want the filter condition to be freely defined, not name.startswith (” small “), and you want to find the name after the name, not simply system.out.println (name); But to be able to do something else. Continue refactoring:

/** * functional interface *@param <T>
 */
@FunctionalInterface
interface Checker<T extends String>{
    boolean check(T t);
}

@FunctionalInterface
interface Out<T>{
    void achievement(T t);
}

public class FunctionalInterfaceTest {
    /** ** call */
    @Test
    public void testLambda(a) {
        List<String> demoList = Arrays.asList("Xiao Ming"."Zing"."Three"."Little red"."Zhao Ritian");
        rollCall(demoList,
                name-> name.startsWith("Z"),
                name->{
                    String rate = name + "Single dog!";
                    System.out.println(rate);
                });
    }

    /** ** ** ** ** ** ** *@param list
     * @param checker
     */
    public void rollCall(List<? extends String> list, Checker checker,Out out){
        for(String name : list){
            if(checker.check(name)){ out.achievement(name); }}}}Copy the code




The results

I accidentally gave something away. Ha, ha, ha

From the above refactoring, it is clear that this is also legal

        Checker checker =  name-> name.startsWith("Z"),
        Out estimator = name->{
            String rate = name + "Single dog!";
            System.out.println(rate);
        };Copy the code

It follows that Lambda and functional interfaces are equivalent.

0 x02 supplement

  • type

    Some people wonder, whyChecker checker = name-> name.startsWith("Z")So when I do that, name will be treated as a String, right?

This is Java type inference, and the general logic is that the compiler knows the type of the input parameter to a functional interface method, so whatever the preceding parameter name is, it will be treated as the parameter type required by the method.

  • Simple abbreviations

    There is another oddityname->name.startsWith("Z")Why is it okay to write this?

    Why not write it as`name->{ return name.startsWith("Z"); }

    Obviously, there’s nothing wrong with that,




However, Idea will have a dashed line, indicating that return is not required





Expand the instructions

Lambda supports this terse return when only one statement needs to be executed. So why refuse?

  • External argument Lambda expressions cannot operate on external objects, because Lambda is essentially a child of the interface and can only access static resources and internal variables of its own.




An error!

The compiler requires that external variables be decorated with final.

  • Combined with method references

    Method referencesMethod ReferencesLambda is a new Java8 feature that works with Lambda, allowing method references to be used to write more concise and readable code when only known methods are executed in Lambda expressions
    List<String> demoList = Arrays.asList("Xiao Ming"."Zing"."Three"."Little red"."Zhao Ritian");
    demoList.forEach(System.out::println);Copy the code

See here must be in the mind can not help but want to say, I wipe, good concise! Four methods are officially cited

Kinds of Method References

Kind Example
Reference to a static method ContainingClass::staticMethodName
Reference to an instance method of a particular object containingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type ContainingType::methodName
Reference to a constructor ClassName::new

Source: docs.oracle.com/javase/tuto…

I don’t think I need to translate it, go out baidu translation 😉


love&peace