[Java] reflection, enumeration, Lambda expression

1, Reflection

1 Definition

The reflection mechanism of Java is to know all the properties and methods of any class in the running state; For any object, we can call any of its methods and properties. Since we can get it, we can modify some type information; This function of dynamically obtaining information and dynamically calling object methods is called the reflection mechanism of Java language.

2 purpose (understanding)

1. In the process of daily third-party application development, we often encounter that a member variable, method or attribute of a class is private or only open to system applications. At this time, we can use the reflection mechanism of Java to obtain the required private members or methods through reflection.

2. The most important use of reflection is to develop various general frameworks. For example, in spring, we hand over all class beans to the spring container for management, regardless of
Whether it is XML configuration Bean or annotation configuration. When we get Bean from the container for dependency injection, the container will read the configuration, and what is given in the configuration is the class
According to this information, spring needs to create those beans, and spring will dynamically create these classes.

3 basic information of reflection

Many objects in Java programs have two types at runtime: runtime type (RTTI) and compile time type, such as Person p = new
Student(); In this code, p is of type Person at compile time and student at run time. The program needs to find the real confidence of objects and classes at run time. By using the reflection program, we can determine which classes the object and class belong to.

4 reflection related classes (important)

Class namepurpose
Class classAn entity representing a class that represents classes and interfaces in a running Java application
Field classRepresents the member variables of the class / properties of the class
Method classMethods representing classes
Constructor classConstruction method of representative class

4.1 Class (origin of reflection mechanism)

Class help documentation An entity representing a class that represents classes and interfaces in a running Java application

After the java file is compiled, it is generated Class file, and the JVM will interpret it at this time Class file, the compiled Java file Class is also parsed into an object by the JVM, which is Java lang.Class . In this way, when the program is running, each class will eventually become an instance of the class object. By applying the reflection mechanism of Java to this instance, we can obtain or even add and change the properties and actions of this class, so as to make this class a dynamic class

4.1.1 relevant methods in class (the use method of the method is in the following example)

  • (important) commonly used methods to obtain class related information
methodpurpose
getClassLoader()Get class loader
getDeclaredClasses()Returns an array containing the objects of all classes and interface classes in the class (including private ones)
forName(String className)Returns the object of the class according to the class name
newInstance()Create an instance of a class
getName()Get the full path name of the class
  • (important) commonly used methods to obtain properties in a class. The return value of the following methods is( Field related )
methodpurpose
getField(String name)Get a public property object
getFields()Get all public property objects
getDeclaredField(String name)Get a property object
getDeclaredFields()Get all attribute objects
  • (understand) get the methods related to annotations in the class
methodpurpose
getAnnotation(Class annotationClass)Returns the public annotation object in this class that matches the parameter type
getAnnotations()Returns all public annotation objects of this class
getDeclaredAnnotation(Class annotationClass)Returns all annotation objects in this class that match the parameter type
getDeclaredAnnotations()Returns all annotation objects of this class
  • (important) get the Constructor related methods in the class (the return value of the following methods is Constructor related)
methodpurpose
getConstructor(Class...<?> parameterTypes)Get the public constructor matching the parameter type in this class
getConstructors()Get all public constructors of this class
getDeclaredConstructor(Class...<?> parameterTypes)Get the constructor matching the parameter type in this class
getDeclaredConstructors()Get all construction methods of this class
  • (important) get the Method related to the Method in the class (the return value of the following Method is Method related)
methodpurpose
getMethod(String name, Class...<?> parameterTypes)Get a public method of this class
getMethods()Get all public methods of this class
getDeclaredMethod(String name, Class...<?> parameterTypes)Get a method of this class
getDeclaredMethods()Get all methods of this class

4.2 reflection example

4.2.1 three ways to obtain Class objects

Before reflection, the first step we need to do is to get the Class object of the Class currently to be reflected, and then achieve the purpose of reflection through the core method of the Class object, that is, for any Class in the running state, we can know all the properties and methods of the Class; For any object, we can call any of its methods and properties. Since we can get it, we can modify some type information.
First, use class Forname ("full pathname of the class"); Static method.
Premise: the full pathname of the class has been specified.
Second, use class method.
Note: it is only applicable to classes that have been explicitly operated before compilation
Third, use the getClass() method of the class object

Example:

class Student{
    //Private attribute name
    private String name = "bit";
    //Public attribute age
    public int age = 18;
    //Construction method without parameters
    public Student(){
        System.out.println("Student()");
    }

    private Student(String name,int age) {
        this.name = name;
        this.age = age;
        System.out.println("Student(String,name)");
    }

    private void eat(){
        System.out.println("i am eat");
    }

    public void sleep(){
        System.out.println("i am pig");
    }

    private void function(String str) {
        System.out.println(str);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class TestDemo {
    public static void main(String[] args) {
        /*
        1.Get Class object through getClass
        */
        Student s1 = new Student();
        Class c1 = s1.getClass();
        /*
        2.Directly through the class name Class, this method is the most safe and reliable, and the program performance is higher
        This means that any class has an implicit static member variable class
        */
        Class c2 = Student.class;
        /*
        3,It is obtained through the forName() static method of Class object, which is used most,
        However, ClassNotFoundException may be thrown
        */
        Class c3 = null;
        try {
            //Note that this is the full path of the class. If there is a package, you need to add the package path
            c3 = Class.forName("Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } 
        //A Class will only have one Class instance in the JVM, that is, the Class we obtained above
        //C1, C2 and C3 are compared with equals and found to be true
        System.out.println(c1.equals(c2));
        System.out.println(c1.equals(c3));
        System.out.println(c2.equals(c3));
    }
}

4.2.2 use of reflection

Next, we write the reflection of the above class to the Student
Note: all reflection related packages are in import Java Lang.reflect package.

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectClassDemo {
    // create object
    public static void reflectNewInstance() {
        try {
            Class<?> classStudent = Class.forName("Student");
            Object objectStudent = classStudent.newInstance();
            Student student = (Student) objectStudent;
            System.out.println("Get students:"+student);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    // Reflection private construction method shields the content to obtain public construction method
    public static void reflectPrivateConstructor() {
        try {
            Class<?> classStudent = Class.forName("Student");
            //Pay attention to the corresponding parameters
            Constructor<?> declaredConstructorStudent =
                    classStudent.getDeclaredConstructor(String.class,int.class);
            //Constructor<?> declaredConstructorStudent = classStudent.getConstructor();
            //Set to true to modify access rights
            declaredConstructorStudent.setAccessible(true);
            Object objectStudent = declaredConstructorStudent.newInstance("Gao Bo",15);
            //Object objectStudent = declaredConstructorStudent.newInstance();
            Student student = (Student) objectStudent;
            System.out.println("Obtain the private construction number and modify the name and age:"+student);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    // Reflection private property
    public static void reflectPrivateField() {
        try {
            Class<?> classStudent = Class.forName("Student");
            Field field = classStudent.getDeclaredField("name");
            field.setAccessible(true);
            //You can modify the value of this property
            Object objectStudent = classStudent.newInstance();
            Student student = (Student) objectStudent;

            field.set(student,"Xiao Ming");

            String name = (String) field.get(student);
            System.out.println("Reflection private property modified name: "+ name);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    // Reflection private method
    public static void reflectPrivateMethod() {
        try {
            Class<?> classStudent = Class.forName("Student");
            Method methodStudent = classStudent.getDeclaredMethod("function",String.class);
            System.out.println("The method name of the private method is:"+methodStudent.getName());
            //Private generally need to be added
            methodStudent.setAccessible(true);
            Object objectStudent = classStudent.newInstance();
            Student student = (Student) objectStudent;
            methodStudent.invoke(student,"I'm for private function Parameters passed by function");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    } 
    
    public static void main(String[] args) {
        //reflectNewInstance();
        //reflectPrivateConstructor();
        //reflectPrivateField();
        reflectPrivateMethod();
    }
}

5. Advantages and disadvantages of reflection

advantage:

  1. For any class, you can know all the properties and methods of this class; Any method of any object can be called
  2. Increase the flexibility and expansibility of the program, reduce the coupling and improve the adaptive ability
  3. Reflection has been used in many popular frameworks, such as Struts, Hibernate, Spring and so on.

Disadvantages:

  1. Using reflection can have efficiency problems. It will reduce the efficiency of the program. See here for details: http://www.imooc.com/article/293679
  2. Reflection technology bypasses the technology of source code, which will bring maintenance problems. Reflective code is more complex than the corresponding direct code.

6 key summary

  1. The meaning of reflection

  2. Several important classes of reflection: Class, Field, Method and Constructor

  3. Learn to make rational use of reflection and be sure to use it in a safe environment.

2, Use of enumerations

1 background and definition

Enumeration is in jdk1 Introduced after 5. The main purpose is to organize a group of constants. Before that, it represents a group of constants. The method of defining constants is usually used:

public static int final RED = 1;
public static int final GREEN = 2;
public static int final BLACK = 3

However, there are some disadvantages in constant examples. For example, there may happen to be a number 1, but it may be misunderstood as RED. Now we can organize it directly with enumeration. In this way, we have types and enumeration types. Instead of ordinary plastic surgery 1

Advantages: organize constants for unified management
Scenario: error status code, message type, color division, state machine, etc

Essence: Java The subclass of lang. Enum, that is, the enumeration class written by yourself inherits this class by default, even if it does not inherit Enum.

2 use

1. switch statement

public enum TestEnum {
    RED,BLACK,GREEN,WHITE;
    public static void main(String[] args) {
        TestEnum testEnum2 = TestEnum.BLACK;
        switch (testEnum2) {
            case RED:
                System.out.println("red");
                break;
            case BLACK:
                System.out.println("black");
                break;
            case WHITE:
                System.out.println("WHITE");
                break;
            case GREEN:
                System.out.println("black");
                break;
            default:
                break;
        }
    }
}

2. Common methods
Common methods of Enum class

Method namedescribe
values()Returns all members of an enumerated type as an array
ordinal()Gets the index location of the enumeration member
valueOf()Converts a normal string to an enumerated instance
compareTo()Compare the order of two enumeration members when they are defined

Example 1:

public enum TestEnum {
    RED,BLACK,GREEN,WHITE;
    public static void main(String[] args) {
        TestEnum[] testEnum2 = TestEnum.values();
        for (int i = 0; i < testEnum2.length; i++) {
            System.out.println(testEnum2[i] + " " + testEnum2[i].ordinal());
        } 
        System.out.println("=========================");
        System.out.println(TestEnum.valueOf("GREEN"));
    }
}

Example 2:

public enum TestEnum {
    RED,BLACK,GREEN,WHITE;
    public static void main(String[] args) {
        //Get the enumeration instance BLACK
        TestEnum testEnum = TestEnum.BLACK;
        //Get enumeration instance RED
        TestEnum testEnum21 = TestEnum.RED;
        System.out.println(testEnum.compareTo(testEnum21));
        System.out.println(BLACK.compareTo(RED));
        System.out.println(RED.compareTo(BLACK));
    }
}

Just said, enumeration is actually a class in Java. Therefore, when defining enumeration, we can also define and use enumeration in this way:

Important: enumeration constructors are private by default

public enum TestEnum {
    RED("red", 1), BLACK("black", 2), WHITE("white", 3), GREEN("green", 4);
    private String name;
    private int key;

    /**
     * 1,When the enumeration object has parameters, you need to provide the corresponding constructor
     * 2,The constructor of enumeration is private by default, which must be kept in mind
     *
     * @param name
     * @param key
     */
    private TestEnum(String name, int key) {
        this.name = name;
        this.key = key;
    }

    public static TestEnum getEnumKey(int key) {
        for (TestEnum t : TestEnum.values()) {
            if (t.key == key) {
                return t;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(getEnumKey(2));
    }
}

3. Enumerate advantages and disadvantages

advantage:

  1. Enumerating constants is simpler and safer.

  2. Enumeration has built-in methods, and the code is more elegant

Disadvantages:

  1. It is not inheritable and cannot be extended

4 enumeration and reflection

4.1 can enumeration get instance objects through reflection?

We just saw in the reflection that even if the construction method of any class is private, we can get its instance object through reflection. Then the construction method of enumeration is also private. Can we get it? Next, let's experiment:

The enumeration class provided above is also used for example:

public enum TestEnum {
    RED("red",1),BLACK("black",2),WHITE("white",3),GREEN("green",4);
    private String name;
    private int key;
    
    /**
     * 1,When the enumeration object has parameters, you need to provide the corresponding constructor
     * 2,The constructor of enumeration is private by default, which must be kept in mind
     * @param name
     * @param key
     */
    private TestEnum (String name,int key) {
        this.name = name;
        this.key = key;
    } 
    
    public static TestEnum getEnumKey (int key) {
        for (TestEnum t: TestEnum.values()) {
            if(t.key == key) {
                return t;
            }
        }
        return null;
    } 
    
    public static void reflectPrivateConstructor() {
        try {
            Class<?> classStudent = Class.forName("TestEnum");
            //Note that the corresponding parameters are passed in and the corresponding construction method is obtained to construct the object. The current enumeration class provides two parameters: String and int.
            Constructor<?> declaredConstructorStudent =
                    classStudent.getDeclaredConstructor(String.class,int.class);
            //Set to true to modify access rights
            declaredConstructorStudent.setAccessible(true);
            Object objectStudent = declaredConstructorStudent.newInstance("green",666);
            TestEnum testEnum = (TestEnum) objectStudent;
            System.out.println("Get private constructor for enumeration:"+testEnum);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    } 
    
    public static void main(String[] args) {
        reflectPrivateConstructor();
    }
}

Output result:

java.lang.NoSuchMethodException: TestEnum.<init>(java.lang.String, int)
	at java.lang.Class.getConstructor0(Class.java:3082)
	at java.lang.Class.getDeclaredConstructor(Class.java:2178)
	at TestEnum.reflectPrivateConstructor(TestEnum.java:40)
	at TestEnum.main(TestEnum.java:54)

Old fellow iron, see no WOW! The exception message is: Java lang.NoSuchMethodException: TestEnum.< Init > (Java. Lang. String, int), what does it mean: there is no corresponding construction method, my God! The construction method of enumeration we provide is that the two parameters are String and int!!!! Where is the problem? Do you remember what we said that all our enumeration classes inherit from Java by default Lang. enum, speaking of inheritance, what did you inherit? Inherits everything except the constructor of the parent class, and the subclass should help the parent class construct!
The class we write does not help the parent class construct! Does that mean that we should provide super in our enumeration class? No, enumeration is special. Although we write two, it adds two parameters by default. Which two parameters? Let's take a look at the source code of Enum class:

protected Enum(String name, int ordinal) {
	this.name = name;
	this.ordinal = ordinal;
}

In other words, our own constructor has two parameters, one is String and the other is int. by default, it will give two parameters, one is String and the other is int. That is to say, here we correctly give four parameters:

public static void reflectPrivateConstructor() {
        try {
            Class<?> classStudent = Class.forName("TestEnum");
            //Note that the corresponding parameters are passed in and the corresponding construction method is obtained to construct the object. The current enumeration class provides two parameters: String and int.
            Constructor<?> declaredConstructorStudent =
            classStudent.getDeclaredConstructor(String.class,int.class,String.class,int.class);
            //Set to true to modify access rights
            declaredConstructorStudent.setAccessible(true);
            //Here, in order to gather the parameters, the last two parameters can be given at will or not. The default value is null
            Object objectStudent = declaredConstructorStudent.newInstance("green",666,"Parent parameter",888);
            TestEnum testEnum = (TestEnum) objectStudent;
            System.out.println("Get private constructor for enumeration:"+testEnum);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

At this time, the result of running the program is:

java.lang.IllegalArgumentException: Cannot reflectively create enum objects
	at java.lang.reflect.Constructor.newInstance(Constructor.java:416)
	at TestEnum.reflectPrivateConstructor(TestEnum.java:46)
	at TestEnum.main(TestEnum.java:55)

Um! Yes, he also reported wrong, but this time is the result I want! At this time, the exception information shows that it is one of my methods. This method is:
newInstance() reported an error! Yes, the problem is here. Let's take a look at the source code of this method and why it throws Java Lang. illegalargumentexception: what about the exception?

Source code display:
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-sZT5hFAj-1646057782417)(C:\Users\Chloe\Desktop\Snipaste_2022-02-28_21-43-15.png)]
Yes, enumeration is filtered here. You can't get the instance of enumeration class through reflection! This question was asked by Alibaba in 2017. If you don't see it, you'll be surprised! Students, remember this pit** The original question is: why is it safe to implement singleton mode by enumerating** Hope students
Remember this question!

5 Summary

1. Enumeration itself is a class, and its construction method is private by default, and is inherited from Java by default lang.Enum
2. Enumeration can avoid reflection and serialization problems
3. Advantages and disadvantages of enumeration

Interview questions (you can review the single case model after learning):
1. Write a singleton mode.

public class Singleton {
    private volatile static Singleton uniqueInstance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            synchronized (Singleton.class){
                if(uniqueInstance == null){//After entering the area, check again. If it is still null, create the instance
                    uniqueInstance = new Singleton();
                }
            }
        } 
        return uniqueInstance;
    }
}

2. Implementing a singleton pattern with static inner classes

class Singleton {
    /** Privatization constructor */
    private Singleton() {
    } 
    /** Provide public access methods */
    public static Singleton getInstance() {
        return UserSingletonHolder.INSTANCE;
    } 
    /** Write a static inner class, which instantiates the outer class */
    private static class UserSingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
} 

public class Main {
    public static void main(String[] args) {
        Singleton u1 = Singleton.getInstance();
        Singleton u2 = Singleton.getInstance();
        System.out.println("Whether the two instances are the same:"+ (u1==u2));
    }
}

3. Implement a singleton mode with enumeration

public enum TestEnum {
    INSTANCE;
    public TestEnum getInstance(){
        return INSTANCE;
    }
    public static void main(String[] args) {
        TestEnum singleton1=TestEnum.INSTANCE;
        TestEnum singleton2=TestEnum.INSTANCE;
        System.out.println("Whether the two instances are the same:"+(singleton1==singleton2));
    }
}

3, Lambda expression

1 background

Lambda expressions are an important new feature in Java SE 8. Lambda expressions allow you to replace functional interfaces with expressions. Lambda expressions, like methods, provide a list of normal parameters and a body that uses these parameters (which can be an expression or a code block). Lambda expression can be regarded as an anonymous function based on λ Calculus gets its name, which can also be called Closure.

1.1 syntax of lambda expression

Basic syntax: (parameters) - > expression or (parameters) - > {statements;}

Lambda expressions consist of three parts:

  1. paramaters: similar to the formal parameter list in the method, the parameters here are the parameters in the functional interface. The parameter types here can be explicitly declared
    It can also be inferred implicitly by the JVM without declaration. In addition, parentheses can be omitted when there is only one inference type.

  2. ->: it can be understood as "used"

  3. Method body: it can be an expression or a code block. It is the implementation of a method in a functional interface. The code block can return a value or nothing. The code block here is equivalent to the method body of the method. If it is an expression, it can also return a value or nothing.

// 1. No parameter is required. The return value is 2
() -> 2

// 2. Receive a parameter (numeric type) and return twice its value
x -> 2 * x

// 3. Accept 2 parameters (numbers) and return their sum
(x, y) -> x + y

// 4. Receive two int integers and return their product
(int x, int y) -> x * y

// 5. Accept a string object and print it on the console without returning any value (it looks like returning void)
(String s) -> System.out.print(s)

1.2 functional interface

To understand Lambda expressions, you first need to understand what is a functional interface. Functional interface definition: an interface has and only has one abstract method.
be careful:

  1. If an interface has only one abstract method, the interface is a functional interface

  2. If we declare the @ FunctionalInterface annotation on an interface, the compiler will require the interface according to the definition of the functional interface. In this way, if there are two abstract methods, the program compilation will report an error. Therefore, in a sense, as long as you ensure that there is only one abstract method in your interface, you can not add this annotation. Plus, it will be detected automatically.

Definition method:

@FunctionalInterface
interface NoParameterNoReturn {
	//Note: there can only be one method
	void test();
}

But this is also possible:

@FunctionalInterface
interface NoParameterNoReturn {
	void test();
	default void test2() {
	System.out.println("JDK1.8 New features, default The default method can have specific implementation");
	}
}

2 basic use of lambda expressions

First, we have several interfaces ready for implementation:

//No return value no parameter
@FunctionalInterface
interface NoParameterNoReturn {
    void test();
}
//No return value a parameter
@FunctionalInterface
interface OneParameterNoReturn {
    void test(int a);
} 
//Multiple parameters without return value
@FunctionalInterface
interface MoreParameterNoReturn {
    void test(int a,int b);
} 
//Return value without parameter
@FunctionalInterface
interface NoParameterReturn {
    int test();
}
//One parameter with return value
@FunctionalInterface
interface OneParameterReturn {
    int test(int a);
} 
//Multiple parameters with return value
@FunctionalInterface
interface MoreParameterReturn {
    int test(int a,int b);
}

As we mentioned above, Lambda expression is essentially an anonymous function. The method of the function is to return the value, method name, parameter list and method body. In Lambda expressions, we only need to care about: parameter list and method body.
See the following example code for specific use:

public class TestDemo {
    public static void main(String[] args) {
        NoParameterNoReturn noParameterNoReturn = ()->{
            System.out.println("No parameter, no return value");
        };
        noParameterNoReturn.test();
        OneParameterNoReturn oneParameterNoReturn = (int a)->{
            System.out.println("No parameter, one return value:"+ a);
        };
        oneParameterNoReturn.test(10);
        
        MoreParameterNoReturn moreParameterNoReturn = (int a,int b)->{
            System.out.println("Multiple parameters without return value:"+a+" "+b);
        };
        moreParameterNoReturn.test(20,30);
        
        NoParameterReturn noParameterReturn = ()->{
            System.out.println("There is a return value and no parameter!");
            return 40;
        };
        //The return value of the receive function
        int ret = noParameterReturn.test();
        System.out.println(ret);
        OneParameterReturn oneParameterReturn = (int a)->{
            System.out.println("There are return values and parameters!");
            return a;
        };
        
        ret = oneParameterReturn.test(50);
        System.out.println(ret);
        
        MoreParameterReturn moreParameterReturn = (int a,int b)->{
            System.out.println("There are multiple parameters with return value!");
            return a+b;
        };
        ret = moreParameterReturn.test(60,70);
        System.out.println(ret);
    }
}

2.1 syntax simplification

  1. Parameter types can be omitted. If they need to be omitted, the type of each parameter should be omitted.

  2. If there is only one parameter in the parameter parentheses, the parentheses can be omitted

  3. If there is only one sentence of code in the method body, the braces can be omitted

  4. If there is only one statement in the method body, which is a return statement, the braces can be omitted and the return keyword can be removed.

Example code:

public static void main(String[] args) {
    MoreParameterNoReturn moreParameterNoReturn = ( a, b)->{
        System.out.println("If there are multiple parameters without return value, the parameter type is omitted:"+a+" "+b);
    };
    moreParameterNoReturn.test(20,30);
        
    OneParameterNoReturn oneParameterNoReturn = a ->{   
        System.out.println("No parameter, a return value,Parentheses can the winning rate:"+ a);
    };
    oneParameterNoReturn.test(10);
    
    NoParameterNoReturn noParameterNoReturn = ()->System.out.println("There is no parameter, no return value, and there is only one line of code in the method body");
    noParameterNoReturn.test();
    
    //There is only one statement in the method body, and it is a return statement
    NoParameterReturn noParameterReturn = ()-> 40;
    int ret = noParameterReturn.test();
    System.out.println(ret);
}

3 variable capture

More operations there is variable capture in Lambda expressions. Only after understanding variable capture can we better understand the scope of Lambda expressions. There will be variable capture in anonymous classes in Java. 3.1 anonymous inner class

3.1 anonymous inner class

An anonymous inner class is an inner class without a name. We're just here to illustrate variable capture, so as long as anonymous inner classes can be used, let's take a simple look at the use of anonymous inner classes.
Here are the students who want to know more about: https://www.cnblogs.com/SQP51312/p/6100314.html
Let's learn through simple code:

class Test {
    public void func(){
        System.out.println("func()");
    }
} 
public class TestDemo {
    public static void main(String[] args) {
        new Test(){
            @Override
            public void func() {
                System.out.println("I am an inner class and override it func This method!");
            }
        };
    }
}

In the main function in the above code, what we see is the simple use of an anonymous inner class.

3.2 variable capture of anonymous inner class

class Test {
    public void func(){
        System.out.println("func()");
    }
} 
public class TestDemo {
    public static void main(String[] args) {
        int a = 100;
        new Test(){
            @Override
            public void func() {
                System.out.println("I am an inner class and override it func This method!");
                System.out.println("I'm capturing variables a == "+a
                        +" I am a constant, or a variable that has not changed its value!");
            }
        };
    }
}

The variable a in the above code is the captured variable. This variable is either modified by final. If it is not modified by final, you should ensure that it is not modified before use. The following code is the wrong code.

public class TestDemo {
    public static void main(String[] args) {
        int a = 100;
        new Test(){
            @Override
            public void func() {
                a = 99;
                System.out.println("I am an inner class and override it func This method!");
                System.out.println("I'm capturing variables a == "+a
                        +" I am a constant, or a variable that has not changed its value!");
            }
        };
    }
}

The code directly compiles and reports an error.

3.3 Lambda's variable capture

Variables can also be captured in Lambda. Let's take a look at the code.

@FunctionalInterface
interface NoParameterNoReturn {
    void test();
}
public static void main(String[] args) {
    int a = 10;
    NoParameterNoReturn noParameterNoReturn = ()->{
        // a = 99; error
        System.out.println("Capture variables:"+a);
    };
    noParameterNoReturn.test();
}

4 use of lambda in Collections

In order to better use Lambda and Java collection classes together, some interfaces have been added to the collection to match Lambda expressions
Connect.

Corresponding interfaceNew method
CollectionremoveIf() spliterator() stream() parallelStream() forEach()
ListreplaceAll() sort()
MapgetOrDefault() forEach() replaceAll() putIfAbsent() remove() replace() computeIfAbsent() computeIfPresent() compute() merge()

For the functions of the above methods, please refer to our help manual. Here we will illustrate the use of some methods. Note: the forEach() method of ` ` Collection is from the interface java Lang. Iterable ` brought it here.

4.1 Collection interface

forEach() method demonstration
The method is in the interface ` ` Iterable ', and the prototype is as follows:

default void forEach(Consumer<? super T> action) {
	Objects.requireNonNull(action);
	for (T t : this) {
		action.accept(t);
	}
}

This method means that the action specified in action is performed on each element in the container.

public static void main(String[] args) {
	ArrayList<String> list = new ArrayList<>();
	list.add("Hello");
	list.add("bit");
	list.add("hello");
	list.add("lambda");
	list.forEach(new Consumer<String>(){
		@Override
		public void accept(String str){
			//Simply traverse the elements in the collection.
			System.out.print(str+" ");
		}
		});
}

Output result: Hello bit hello lambda
We can modify it to the following code:

public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
	list.add("Hello");
	list.add("bit");
	list.add("hello");
	list.add("lambda");
	//It refers to calling a method without parameters, which executes the statement in curly braces, which is the content of the original function body.
	list.forEach(s -> {
		System.out.println(s);
	});
}

Output result: Hello bit hello lambda

4.2 List interface

Demonstration of sort() method
sort method source code: this method sorts the container elements according to the comparison rules specified by c.

public void sort(Comparator<? super E> c) {
	final int expectedModCount = modCount;
	Arrays.sort((E[]) elementData, 0, size, c);
	if (modCount != expectedModCount) {
		throw new ConcurrentModificationException();
	} 
    modCount++;
}

Use example:

public static void main(String[] args) {
	ArrayList<String> list = new ArrayList<>();
	list.add("Hello");
	list.add("bit");
	list.add("hello");
	list.add("lambda");
	list.sort(new Comparator<String>() {
	@Override
	public int compare(String str1, String str2){
		//Note that the length is compared here
		return str1.length()-str2.length();
	}
	});
	System.out.println(list);
}

Output result: bit, Hello, hello, lambda

Modify to lambda expression:

public static void main(String[] args) {
	ArrayList<String> list = new ArrayList<>();
	list.add("Hello");
	list.add("bit");
	list.add("hello");
	list.add("lambda");
	//Call the method with 2 parameters and return the difference of length
	list.sort((str1,str2)-> str1.length()-str2.length());
	System.out.println(list);
}

Output result: bit, Hello, hello, lambda

4.3 Map interface

forEach() of HashMap
The prototype of the method is as follows:

default void forEach(BiConsumer<? super K, ? super V> action) {
    Objects.requireNonNull(action);
	for (Map.Entry<K, V> entry : entrySet()) {
		K k;
		V v;
	try {
		k = entry.getKey();
		v = entry.getValue();
	} catch(IllegalStateException ise) {
		// this usually means the entry is no longer in the map.
		throw new ConcurrentModificationException(ise);
} 
        action.accept(k, v);
	}
}

The function is to perform the operation specified in action on each Map in the Map.
Code example:

public static void main(String[] args) {
	HashMap<Integer, String> map = new HashMap<>();
	map.put(1, "hello");
	map.put(2, "bit");
	map.put(3, "hello");
	map.put(4, "lambda");
	map.forEach(new BiConsumer<Integer, String>(){
		@Override
		public void accept(Integer k, String v){
			System.out.println(k + "=" + v);
		}
	});
}

Output result:
1=hello 2=bit 3=hello 4=lambda
Code after using lambda expression:

public static void main(String[] args) {
	HashMap<Integer, String> map = new HashMap<>();
	map.put(1, "hello");
	map.put(2, "bit");
	map.put(3, "hello");
	map.put(4, "lambda");
	map.forEach((k,v)-> System.out.println(k + "=" + v));
}

Output result:
1=hello 2=bit 3=hello 4=lambda

5 Summary

Lambda expression has obvious advantages. At the code level, it makes the code very concise. The disadvantages are also obvious, and the code is not easy to read.
advantage:

  1. Simple code and rapid development

  2. Convenient functional programming

  3. It is very easy to perform parallel computing

  4. Java introduces Lambda to improve collection operation

Disadvantages:

  1. Poor code readability

  2. In non parallel computing, many computing may not have the high performance of the traditional for

  3. Not easy to debug

Keywords: Java Lambda Spring data structure reflection

Added by panic! on Tue, 01 Mar 2022 09:22:31 +0200