In the interview, we always encounter reflection mechanism and application?? Don't come and review!

Reflection mechanism and Application

What is reflection

In the program running state, for any class or object, all properties and methods of the class (including private properties and methods) can be obtained. This function of dynamically obtaining information and dynamically calling object methods is called reflection mechanism. In short, through reflection, classes are completely transparent to us. You can get anything you want.

Class object

Every Class we create is also an object, that is, the Class itself is Java Instance object of lang.Class class. This instance object is called a Class object, that is, a Class object.

The instance object of Class represents the classes and interfaces in the running Java application, that is, each instance in the JVM. Each Class has a unique Class

object

Class class has no public construction method. Class object is automatically constructed by Java virtual machine when loading class
The Class object is used to provide information about the Class itself, such as how many construction methods there are, how many attributes there are, and what common methods there are
Three ways to get Class objects
It can be obtained in the source code phase. Class.forName("full class name"). Load the bytecode file into memory and return the class object, which is mostly used in the configuration file and the configuration file defined by the class name.
Get the class name in the class object phase class. This method is mostly used for parameter transfer
Get: new class name () in the Runtime stage getClass(). This method is defined in the Object class (all classes inherit from Object), so all classes will inherit this method. It is mostly used to obtain bytecode from objects.

Get Class object case

public class GetClass {

    @Test
    public void classForName() throws ClassNotFoundException {
        // Mode 1 class Forname ("full class name")
        final Class<?> clazz1 = Class.forName("cn.wujiwen.basic.reflect.ExampleClass");
        System.out.println("class1:" + clazz1);
    }

    @Test
    public void nameClass(){
        // Mode II name class
        final Class<ExampleClass> clazz2 = ExampleClass.class;
        System.out.println("class2:" + clazz2);
    }

    @Test
    public void ObjectGetClass(){
        // Method 3: instance object getClass()
        ExampleClass exampleClass = new ExampleClass();
        Class<?> clazz3 = exampleClass.getClass();
        System.out.println("class3:" + clazz3);
    }

    // The same section code file (*. class) will only be loaded once during a program run. The class object obtained by either method is the same.
    @Test
    public void all() throws ClassNotFoundException {
        Assertions.assertSame(Class.forName("cn.wujiwen.basic.reflect.ExampleClass") , ExampleClass.class);
    }
}

Function of Class object

Here we will briefly record three common functions. For more methods, you can read the class source code completely

1. Get member variable

//Gets the member variables of all public modifiers
Field[] getFields() 
//Gets the member variable of the public modifier with the specified name         
Field getField(String name)  
//Gets all member variables, regardless of modifiers
Field[] getDeclaredFields() 
//Gets the specified member variable, regardless of the modifier 
Field getDeclaredField(String name)  

2. Get construction method

//Get constructors for all public modifiers
Constructor<?>[] getConstructors()
//Gets the constructor of the specified public modifier
Constructor<T> getConstructor(class<?>... parameterTypes)
//Get all constructors, regardless of modifiers
Constructor<?>[] getDeclaredConstructors() 
//Gets the specified constructor, regardless of modifiers 
Constructor<T> getDeclaredConstructor(class<?>... parameterTypes)  //Gets the specified constructor, regardless of modifiers

3. Get member method

//Gets the member method of all public modifiers
Method[] getMethods()   
//Gets the member method of the public modifier with the specified name        
Method getMethod(String name, class<?>... parameterTypes) 
//Gets all member methods, regardless of modifiers
Method[] getDeclaredMethods()  
//Gets the member method of the specified name, regardless of the modifier
Method getDeclaredMethod(String name, class<?>... parameterTypes) 

Let's test one class by one. First, prepare the class and attribute information required by the above functional methods

public class ExampleClass {
    // public decorated properties
    public String publicField;
    // private decorated properties
    private String privateField;
    // default
    String defaultField;
    // protected modified house type
    protected String protectedField;

    // The protected parameterless construction conflicts with the public parameterless construction, and the overwrite operation will occur
    protected ExampleClass(){

    }
    // public is a parameter constructor
    public ExampleClass(String privateField){
        this.privateField = privateField;
    }
    
    public void publicMethod(){

    }

    private void privateMethod(){

    }

    protected void protectedMethod(){

    }

    void defaultMethod(){

    }
		
		public void noParamsMethod(){
        System.out.println("this is noParamsMethod");
    }
    
    public void paramsMethod(String params){
        System.out.println("this is paramsMethod,params is " + params);
    }
}

Next, we will test the use and permission information of each function

Get member variable

@Test
public void getField() throws NoSuchFieldException {
    Class<ExampleClass> exampleClassClass = ExampleClass.class;
    
		Field[] fields = exampleClassClass.getFields();
    System.out.println(Arrays.asList(fields));
		// Only one public attribute information is returned
		// [public java.lang.String cn.wujiwen.basic.reflect.ExampleClass.publicField]

    Field publicField = exampleClassClass.getField("publicField");
    System.out.println(publicField);
		// It can be obtained. If it is set to other attribute parameters, an error will be reported
		// public java.lang.String cn.wujiwen.basic.reflect.ExampleClass.publicField

    Field[] declaredFields = exampleClassClass.getDeclaredFields();
    System.out.println(Arrays.asList(declaredFields));
		// All attribute information is returned, regardless of modifier information
		// [public java.lang.String cn.wujiwen.basic.reflect.ExampleClass.publicField, private java.lang.String cn.wujiwen.basic.reflect.ExampleClass.privateField, java.lang.String cn.wujiwen.basic.reflect.ExampleClass.defaultField, protected java.lang.String cn.wujiwen.basic.reflect.ExampleClass.protectedField]

    Field privateField = exampleClassClass.getDeclaredField("privateField");
    System.out.println(Arrays.asList(privateField));
		// private java.lang.String cn.wujiwen.basic.reflect.ExampleClass.privateField
}

Get constructor

@Test
public void getConstructor() throws NoSuchMethodException {
    Class<ExampleClass> exampleClassClass = ExampleClass.class;
    
    Constructor<?>[] constructors = exampleClassClass.getConstructors();
    System.out.println(Arrays.toString(constructors));
    // [public cn.wujiwen.basic.reflect.ExampleClass(java.lang.String)]

    Constructor<ExampleClass> constructor = exampleClassClass.getConstructor(String.class);
    System.out.println(constructor);
		// public cn.wujiwen.basic.reflect.ExampleClass(java.lang.String)

    Constructor<?>[] declaredConstructors = exampleClassClass.getDeclaredConstructors();
    System.out.println(Arrays.toString(declaredConstructors));
    // [public cn.wujiwen.basic.reflect.ExampleClass(java.lang.String), protected cn.wujiwen.basic.reflect.ExampleClass()]
    
		Constructor<ExampleClass> declaredConstructor = exampleClassClass.getDeclaredConstructor(null);
    System.out.println(declaredConstructor);
		// protected cn.wujiwen.basic.reflect.ExampleClass()
		
}

Get member method

@Test
public void getMethod() throws Exception {
    Class<ExampleClass> exampleClassClass = ExampleClass.class;
    Method[] methods = exampleClassClass.getMethods();
    System.out.println(Arrays.toString(methods));
		// Returns all public information, including wait and other method information in the Object class
		// [public void cn.wujiwen.basic.reflect.ExampleClass.publicMethod(), public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
    
		Method publicMethod = exampleClassClass.getMethod("publicMethod");
    System.out.println(publicMethod);
		// public void cn.wujiwen.basic.reflect.ExampleClass.publicMethod()
		
    Method[] declaredMethods = exampleClassClass.getDeclaredMethods();
    System.out.println(Arrays.toString(declaredMethods));
		// Only all methods in this class are returned
		// [private void cn.wujiwen.basic.reflect.ExampleClass.privateMethod(), public void cn.wujiwen.basic.reflect.ExampleClass.publicMethod(), protected void cn.wujiwen.basic.reflect.ExampleClass.protectedMethod(), void cn.wujiwen.basic.reflect.ExampleClass.defaultMethod()]

    Field protectedField = exampleClassClass.getDeclaredField("protectedField");
    System.out.println(protectedField);
		// protected java.lang.String cn.wujiwen.basic.reflect.ExampleClass.protectedField

    Method enclosingMethod = exampleClassClass.getEnclosingMethod();
    System.out.println(enclosingMethod);
		// null has no internal anonymous method orz
}

Function of Field object

Common functions usually include obtaining attribute values, assigning new values, etc

@Test
public void modifyField() throws Exception {
    ExampleClass exampleClass = new ExampleClass();
    Class<? extends ExampleClass> classClass = exampleClass.getClass();
    Field publicField = classClass.getField("publicField");
    Object publicFieldValue = publicField.get(exampleClass);
    System.out.println(publicFieldValue);

    Field privateField = classClass.getDeclaredField("privateField");
    // //Ignore the check of access rights, violent reflection
    privateField.setAccessible(true);
    // Get value
    Object privateFieldVale = privateField.get(exampleClass);
    System.out.println(privateFieldVale);
    // Assign new value
    privateField.set(exampleClass,"newPrivateValue");
    Object newValue = privateField.get(exampleClass);
    System.out.println(newValue);
}

Function of Method object

Execute the method Object invoke(Object obj,Object... args);
Get parameter getParameters()

@Test
public void methodFun() throws Exception {
    ExampleClass exampleClass = new ExampleClass();
    Class<? extends ExampleClass> classClass = exampleClass.getClass();
    Method noParamsMethod = classClass.getMethod("noParamsMethod");
    // Execution method
    noParamsMethod.invoke(exampleClass);

    Method paramsMethod = classClass.getMethod("paramsMethod", String.class);
    // Get parameters
    Parameter[] parameters = paramsMethod.getParameters();
    System.out.println(Arrays.toString(parameters));
    // Execution method
    paramsMethod.invoke(exampleClass,"This is a parameter");
}

extend

In the process of sorting out field, method and constructor, we found that they all inherit from the AccessibleObject class, setAccessible(true) mentioned above; Method is a function provided by this class. The following also introduces a very common annotation function in the framework. In reflection, we can obtain the annotations of the above three objects, and then complete more customization functions

First, we add the annotation information in the jdk in ExampleClass and try to obtain the annotation information by reflection

@Deprecated
public class ExampleClass {
    // public decorated properties
    @Deprecated
    public String publicField;
    @Deprecated
    public void publicMethod(){

    }
}

We add a common out of date annotation to the class name attribute and method respectively

@Test
public void getAnnotation() throws Exception {
    ExampleClass exampleClass = new ExampleClass();
    Class<? extends ExampleClass> classClass = exampleClass.getClass();
    Annotation[] classAnnotations = classClass.getDeclaredAnnotations();
    System.out.println(Arrays.toString(classAnnotations));

    Field publicField = classClass.getField("publicField");
    Annotation[] fieldAnnotations = publicField.getAnnotations();
    System.out.println(Arrays.toString(fieldAnnotations));

    Method publicMethod = classClass.getMethod("publicMethod");
    Deprecated annotation = publicMethod.getAnnotation(Deprecated.class);
    System.out.println(annotation);
}

In this way, we can get the annotation information on the related objects.

Practical application

Above, we have listed many common functions and usages in reflection in combination with cases. Below, we will apply the above functions in development practice in combination with a simple functional requirement. Because they are simple applications, they are not used as actual development references.

Function description

Now we have a set of parsed complete data (read through excel or xml, etc.), which need to be assembled into the corresponding object according to the requirements for later application. For example, we have several sets of statistical data, one is the school's student information data, the other is the school's teacher information data, It has been parsed from the three-party table through the parsing tool and encapsulated into an array set. The data corresponding to the array index is known, such as the representative name of index=0

Let's get the data ready first

List<List<Object>> teachers = new ArrayList<>();
List<List<Object>> students = new ArrayList<>();

@BeforeEach
public void data(){
    List<Object> teacher1 = new ArrayList<>();
    teacher1.add("Miss Zhang");
    teacher1.add(20);
    teacher1.add("13011111111");
    teacher1.add("language");

    List<Object> teacher2 = new ArrayList<>();
    teacher2.add("Miss Li");
    teacher2.add(40);
    teacher2.add("13811111111");
    teacher2.add("mathematics");

    teachers.add(teacher1);
    teachers.add(teacher2);

    List<Object> student1 = new ArrayList<>();
    student1.add("Li Hua");
    student1.add(10);
    student1.add("Class 1, grade 3");

    List<Object> student2 = new ArrayList<>();
    student2.add("Tie Zhu Zhao");
    student2.add(11);
    student2.add("Class 2, grade 4");

    students.add(student1);
    students.add(student2);
}

[[Mr. Zhang, 20, 13011111111, Chinese], [Mr. Li, 40, 13811111111, mathematics]]
[[Li Hua, grade 10, class 1, grade 3], [Zhao Tiezhu, grade 11, class 2, grade 4]]
Now there are two classes, Student and Teacher, which need to receive the corresponding data information

public class Student {
    /**
     * Student name
     */
    private String studentName;
    /**
     * Class name
     */
    private String className;
    /**
     * Age
     */
    private Integer age;
		
		// setter getter ...
}

public class Teacher {
    private String name;
    private String mobile;
    private String subject;
    private Integer age;
		// setter getter ...
}

Next, we will put the above two sets of inputs into the corresponding objects through reflection, and accurately correspond to their respective attributes

We can customize the annotation, apply the annotation content to each field, mark the specific index value of the field in the array, and then assign it to the field.

Customize a field index annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {FIELD})
public @interface FieldIndex {
    /**
     * Corresponding index
     * @return
     */
    int index();
}
reform Student and Teacher class

java
public class Student {
    /**
     * Student name
     */
    @FieldIndex(index = 0)
    private String studentName;
    /**
     * Class name
     */
    @FieldIndex(index = 2)
    private String className;
    /**
     * Age
     */
    @FieldIndex(index = 1)
    private Integer age;
}

public class Teacher {
    @FieldIndex(index = 0)
    private String name;
    @FieldIndex(index = 2)
    private String mobile;
    @FieldIndex(index = 3)
    private String subject;
    @FieldIndex(index = 1)
    private Integer age;
}

Define a tool method

/**
 *
 * @param t Class to bind
 * @param data Processed data
 * @param <T>
 * @return
 */
public <T> void bind(T t,List<Object> data){
    Class<?> clazz = t.getClass();
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
        // Gets the annotation of the field
        FieldIndex annotation = field.getAnnotation(FieldIndex.class);
        // Valid annotation
        if (annotation != null && annotation.index() >= 0){
            // Gets the index value in the annotation
            int index = annotation.index();
            // Get data in data
            Object value = data.get(index);
            // Ignore check
            field.setAccessible(true);
            // Copy to this field
            try {
                field.set(t,value);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}

test

@Test
public void dataBind(){
    List<Teacher> teacherList = new ArrayList<>();
    for (List<Object> teacherArr : teachers) {
        Teacher teacher = new Teacher();
        bind(teacher,teacherArr);
        teacherList.add(teacher);
    }
    List<Student> studentList = new ArrayList<>();
    for (List<Object> studentArr : students) {
        Student student = new Student();
        bind(student,studentArr);
        studentList.add(student);
    }
    System.out.println(teacherList);
    System.out.println(studentList);

}

In this way, we have completed a simple data binding. There are many extensions of similar functions, such as data verification on a sub basis. In our actual development process, there are many such processing methods. The use of reflection mechanism can greatly facilitate our development.

Finally, I wish you all success in your studies and satisfaction offer , fast promotion increase , go to the peak of life.

If you can, please give me a three company to support me??? [white whoring data]

Keywords: Java Programming Big Data Spring reflection

Added by joopeon on Sat, 22 Jan 2022 00:20:50 +0200