Reflection: the soul of frame design

Posted by cs.punk on Thu, 18 Nov 2021 18:01:25 +0100

  encapsulating the components of a class into other objects is the mechanism of reflection.

  benefits of reflection:

  1. You can manipulate these objects while the program is running
  2. It can decouple and improve the scalability of the program

1. Method of obtaining Class object

  method 1: Class.forName("full Class name"): load the bytecode file into memory and return the Class object

  method 2: class name. Class: obtained through the class attribute of the class name

  method 3: Object. getClass(): the getClass() method is defined in the Object class


   note: the same bytecode file will only be loaded once in a program run, and the Class object obtained by either method is the same.

package com.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
}
package com.basic;

import com.entity.Person;

public class Demo {

    public static void main(String[] args) throws ClassNotFoundException {
        // In this way, the Class obtained is mostly used in the configuration file, the Class name is defined in the configuration file, the file is read, and the Class is loaded
        Class<?> personClass1 = Class.forName("com.entity.Person"); // Package name + class name: full class name
        System.out.println(personClass1);

        // Mostly used for parameter passing (we often use it)
        Class<Person> personClass2 = Person.class;
        System.out.println(personClass2);

        Person p = new Person();
        Class<? extends Person> personClass3 = p.getClass();
        System.out.println(personClass3);

        // Compare whether the three Class instances are equal
        System.out.println(personClass1 == personClass2);
        System.out.println(personClass2 == personClass3); // The results are all true, so the same instance is created. It will only be loaded once to produce an instance
    }
}

2. Use Class object to get member variables

  • Field[] getFields(): get the member variables of all public modifiers
  • Field getField(String name): gets the public decorated member variable of the specified name
  • Field [] getdeclaraedfields(): get all member variables, regardless of modifiers
  • Field getdeclaraedfield (string name): get the member variable with the specified name, regardless of the modifier
  • void set(Object obj, Object value): sets a value for a member variable
  • get(Object obj): get the value of the member variable
  • setAccessible(true): violent reflection, enabling it to access private decorated member variables
package com.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
    public String a;
    public String testA;
    protected String b;
    String c;
}

package com.basic;

import com.entity.Person;

import java.lang.reflect.Field;
import java.util.Arrays;

public class Demo {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        // Get Class instance
        Class<Person> personClass = Person.class;
        // Gets the member variables of all public modifiers
        Field[] fields = personClass.getFields();
        System.out.println(Arrays.toString(fields));

        // Gets the member variable decorated with the specified name public
        Field testA = personClass.getField("testA");
        System.out.println(testA);
        // Set values for fields
        Person p = new Person();
        testA.set(p, "Zhang San"); // Set the value by reflection
        // Get the value of the field
        System.out.println(testA.get(p)); // Take value by reflection

        // Gets all member variables, regardless of modifiers
        Field[] declaredFields = personClass.getDeclaredFields();
        System.out.println(Arrays.toString(declaredFields));

        // Gets the member variable with the specified name, regardless of the modifier
        Field name = personClass.getDeclaredField("name");
        System.out.println(name);
        // Set a value for the private field
        name.setAccessible(true); // Violence reflects variables that enable it to access private modifiers
        name.set(p, "Li Si");
        System.out.println(name.get(p));
    }
}

3. Obtain the construction method by using the Class object

  • Constructor<?> [] getconstructors(): get the constructor of all public modifiers
  • Constructor getconstructor (class <? >... parameterfTypes): gets the constructor of the public modifier of the specified parameter list
  • Constructor getdeclaraedconstructor (class <? >... parameterfTypes): get the construction method of the specified parameter list, regardless of modifiers
  • Constructor<?> [] getdeclaraedconstructors(): get all construction methods, regardless of modifiers
  • T newInstance(Object... initargs): create an object with the obtained construction method
  • If you create an object with an empty parameter constructor, the operation can be simplified: the newInstance method of the Class object
package com.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
}
package com.basic;

import com.entity.Person;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

public class Demo {

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // Get Class instance
        Class<Person> personClass = Person.class;

        // Gets the constructor of all public modifiers
        Constructor<?>[] constructors = personClass.getConstructors();
        System.out.println(Arrays.toString(constructors));

        // Gets the constructor of the public modifier with the specified name
        Constructor<Person> constructor = personClass.getConstructor(String.class, Integer.class);
        System.out.println(constructor);
        // Create objects by reflection
        Person person = constructor.newInstance("Zhang San", 18);
        System.out.println(person);

        // A simplified pattern of the construction method for obtaining null parameters
        Person person1 = personClass.newInstance();
        System.out.println(person1);
    }
}

4. Use Class object to get member methods

  • Method[] getMethods(): get all public methods in the class, including the public methods in the parent class
  • Method getMethod(String name, class <? >... parameterTypes): gets the method modified by the specified public
  • Method[] getDeclaredMethods(): get all the methods declared in the class, excluding the methods of the parent class
  • Method getdeclaraedmethod (string name, class <? >... parameterTypes)
  • Object invoke(Object obj, Object... args): execute the method
  • String getName: get method name
package com.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;

    private String lookMovie(String movieName, int age) {
        System.out.println(movieName + "::" + age);
        return movieName;
    }
}
package com.basic;

import com.entity.Person;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Demo {

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        // Get Class instance
        Class<Person> personClass = Person.class;

        // Get the methods of all public modifiers (including the methods of the parent class)
        Method[] methods = personClass.getMethods();
        System.out.println(Arrays.toString(methods));

        // Gets the method of the specified public modifier
        Method setName = personClass.getMethod("setName", String.class);
        System.out.println(setName);
        // Execute this method
        Person person = personClass.newInstance(); // Create null parameter construction method by reflection
        setName.invoke(person, "Zhang San"); // Execution method
        System.out.println(person);

        // Get all methods (methods without parent class)
        Method[] declaredMethods = personClass.getDeclaredMethods();
        System.out.println(Arrays.toString(declaredMethods));

        // Get the specified method (both private and public modifiers can be used)
        Method lookMovie = personClass.getDeclaredMethod("lookMovie", String.class, int.class);
        System.out.println(lookMovie);
        // Execute private method
        lookMovie.setAccessible(true); // Violent reflection, so that the method of performing private modification does not report an error
        Object invoke = lookMovie.invoke(person, "Li Si", 28);
        System.out.println(invoke);
    }
}

Topics: Java