This is the 20th day of my participation in the More text Challenge. For more details, see more text Challenge


Related articles

Java Annotations and Reflection series: Java Annotations and reflection series


preface

We’ve covered the process of getting a reflected object and loading a class. Now we need to learn how to use a reflected class object!

Get the structure of the runtime class

The complete structure of a runtime class can be obtained by reflection:

①FIeld (property)

(2) What is the Method?

(3) Constructor

④Superclass (Superclass)

() 5.

⑥Annotation

Example code: Person class:

import lombok.Data;

@Data
public class Person extends Object{
    private String name;
    private int high;
    private String like;
    public Integer age;

    public Person(a){}private void priTest(String name){}public Person(String name){}}Copy the code

Test code:

public class test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
        Class c1 = Class.forName("Com. Dbright. Java reflection. Person");/ / class.forname
        Person person = new Person();
        Class c2 = person.getClass();// Object.class
        Class c3 = Person.class;// Class.object

        // Get the name of the class
        System.out.println("c1"+c1.getName());
        System.out.println("c2"+c2.getName());
        System.out.println("c3"+c3.getName());

        System.out.println("Simple:"+c1.getSimpleName());

        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
        // Get the properties of the class
        Field[] fields = c1.getFields();// Only public properties can be obtained
        for (Field field : fields) {
            System.out.println("getFields:"+field);
        }
        Field[] fields1 = c1.getDeclaredFields();// Get all attributes
        for (Field field : fields1) {
            System.out.println("getDeclaredFields:"+field);
        }
        // Get the attribute with the specified name
        System.out.println("getDeclaredField:"+c1.getDeclaredField("name"));

        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
        // Get the method of the class -- contains the method of the superclass
        Method[] methods = c1.getMethods();// Only public methods are available
        for (Method method : methods) {
            System.out.println("getMethods:"+method);
        }
        Method[] methods1 = c1.getDeclaredMethods();// Get all methods
        for (Method method : methods1) {
            System.out.println("getDeclaredMethods"+method);
        }
        // Get the specified method
        Method method = c1.getMethod("getName".null);// Pass null
        Method method1 = c1.getMethod("setName", String.class);// Object with parameters
        System.out.println(Get the specified method 1:+method);
        System.out.println(Get the specified method 2:+method1);


        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
        // Get the constructor, no comment added, as above, public and private
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("getConstructors:"+constructor);
        }
        Constructor[] constructors1 = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors1) {
            System.out.println("getDeclaredConstructors:"+constructor);
        }
        // Get the specified constructor -- which constructor it is based on the arguments
        System.out.println(Gets the specified constructor:+c1.getConstructor());
        System.out.println(Gets the specified constructor:+c1.getConstructor(String.class)); }}Copy the code

Execution Result:

Second, dynamically create object execution method

This explains how to use reflection to get the properties, methods, constructors, and so on of a class. So how do you dynamically create objects and execute methods?

Create a Class object: Call the newInstance () method on the Class object

  • A class must have a constructor that takes no arguments
  • Class’s constructor needs to have sufficient access

The constructor of the class is explicitly called at the time of the operation, and the parameters are passed in

  • GetDeclaredConstructor (Classs… ParameterTypes) gets the constructor for the specified parameterTypes of this class
  • Pass an array of objects as constructor parameters that contain the parameters required by the constructor
  • Instantiate an object through Constructor

3, call the specified Method: call the Method in the class by reflection, through the Method class

  • GetMethod (String name, Class… ParameterTypes) Method takes a Method object and sets the parameterTypes required for this Method to operate
  • Invoke (Object obj, Object[] args) and pass the parameter information of the obj Object to be set to the method

4, Object Invoke (Object obj, Object… The args)

  • Object corresponds to the return value of the original method. If the original method does not return a value, null is returned
  • If the original method is static, the Object obj parameter can be null
  • If the original method parameter list is empty, Object[] args is null
  • If the original method is declared private, then you need to explicitly call the setAccessible (True) method of the method object before calling this invoke () method to make the private method accessible

5, setAccessible

  • Method and Field and Constructor objects have setAccessible () methods
  • SetAccessible Enables or disables the access security check
  • A value of true indicates that the reflected object should be used without Java language access checks
    • Improve the efficiency of reflection. Set this to true if reflection must be used in your code and the sentence code needs to be called frequently
    • Make private members that are otherwise inaccessible accessible
  • A value of false indicates that the reflected object should be subjected to Java language access checks

Example code for this rule:

import lombok.Data;

@Data
public class Person extends Object{
    private String name;
    private int high;
    private String like;
    public Integer age;

    public Person(a){}private void priTest(String name){}public Person(String name){
        this.name = name; }}Copy the code

Test code:

/** * Dynamically create objects by reflection */
public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {

        // Get the class object
        Class c = Class.forName("Com. Dbright. Java reflection. Person");

        // Construct an object, essentially calling the parameterless constructor
        Person person = (Person) c.newInstance();
        System.out.println("person:"+person);

        // Create an object with a parameter constructor
        Constructor constructor = c.getDeclaredConstructor(String.class);
        Person person1 = (Person) constructor.newInstance("ding");// Need to override the toString method
        System.out.println("person1:"+person1);

        // Obtain and operate methods by reflection
        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
        Person person2 = (Person) c.newInstance();
        Method setLike = c.getDeclaredMethod("setLike", String.class);
        setLike.invoke(person2,"Phishing");
        System.out.println("person2:"+person2);

        // Operate properties by reflection
        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
        Person person3 = (Person) c.newInstance();
        Field name = c.getDeclaredField("name");

        // Turn off permission checks. You can't directly manipulate private properties. You need to turn off security checks, properties or methods
        name.setAccessible(true);

        name.set(person3,"Ding Da");
        System.out.println("name:"+name.getName()); }}Copy the code

Execution Result:

      • Performance test:

So what’s the difference between these two approaches?

public class Test02 {
    public static void main(String[] args) throws NoSuchMethodException {
        test1();
        test2();
        test3();
    }

    /** * Call */ in normal mode
    public static void test1(a){
        Person person = new Person();

        // Obtain the current system time
        long startTime = System.currentTimeMillis();
        for (int i=0; i<2000000000; i++){
            person.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Time required for normal mode invocation:"+(endTime-startTime)+"ms");
    }
    /** * Reflect call */
    public static void test2(a) throws NoSuchMethodException {
        Person person = new Person();
        Class c = person.getClass();
        Method getName = c.getDeclaredMethod("getName".null);
        // Obtain the current system time
        long startTime = System.currentTimeMillis();
        for (int i=0; i<2000000000; i++){
            getName.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Time required for normal mode invocation:"+(endTime-startTime)+"ms");
    }
    /** * Reflect mode calls off detection */
    public static void test3(a) throws NoSuchMethodException {
        Person person = new Person();
        Class c = person.getClass();
        Method getName = c.getDeclaredMethod("getName".null);
        // Obtain the current system time
        long startTime = System.currentTimeMillis();
        getName.setAccessible(true);// Turn off safety detection
        for (int i=0; i<2000000000; i++){
            getName.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Time required for normal mode invocation:"+(endTime-startTime)+"ms"); }}Copy the code

The execution result is as follows:

Conclusion: Using reflection call is inefficient, if you need to use reflection call frequently, please turn off security check!!

3. Reflection operation generics
  • Java uses the generics eraser mechanism to introduce generics. Generics in Java are only used by the compiler Javac to ensure data security and avoid casting problems. However, once the compilation is complete, all types related to generics are erased
  • To manipulate these types through reflection, Java has added ParameterizedType, GenericArrayType, TypeVariable, and WildcardType to represent types that cannot be grouped into a Class Class but have the same name as the original type
    • ParameterizedType: indicates a ParameterizedType, such as Collection
    • GenericArrayType: represents an array type whose element type is a parameterized type or a type variable
    • TypeVariable: is a common interface for variables of various types
    • WildcardType: represents a WildcardType expression

Test code is as follows:

public class Test03 {
    // Get generics by reflection
        public void test01(Map<String, Person> map, List<Person> list){
            System.out.println("test01");
        }

        public Map<String, Person> test02(a){
            System.out.println("test02");
            return null;
        }

        public static void main(String[] args) throws NoSuchMethodException {
            Method method = Test03.class.getMethod("test01", Map.class, List.class);

            Type[] geners = method.getGenericParameterTypes();

            for (Type gener : geners) {
                System.out.println("*" + gener);
                if (gener instanceof ParameterizedType){
                    Type[] actuals = ((ParameterizedType)gener).getActualTypeArguments();
                    for (Type actual : actuals) {
                        System.out.println(actual);
                    }
                }
            }

            method = Test03.class.getMethod("test02".null);
            Type geners1 = method.getGenericReturnType();

            if (geners1 instanceof ParameterizedType){
                Type[] actuals = ((ParameterizedType)geners1).getActualTypeArguments();
                for(Type actual : actuals) { System.out.println(actual); }}}}Copy the code

Execution Result:

Four, reflection operation annotation

How do you use annotations and reflection?

public class Test04 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c = Person1.class;

        // Get annotations by reflection
        Annotation[] annotations = c.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("annotation:"+annotation);
        }

        // Get the value of the annotation value
        classAno classAno1 = (classAno) c.getAnnotation(classAno.class);
        String value = classAno1.value();
        System.out.println("value:"+value);

        // Get the specified annotation for the class
        Field field = c.getDeclaredField("name");
        methodAno methodAno1 = field.getAnnotation(methodAno.class);
        System.out.println("name:"+methodAno1.name());
        System.out.println("type:"+methodAno1.type());
        System.out.println("length:"+methodAno1.length()); }}/** * test class */
@Data
@classAno("Person1")
class Person1{
    @methodano (name = 1,type = 1,length = 2) @methodano (name = 1,type = 1,length = 2)
    private String name;
    private int high;
    private String like;
    public Integer age;
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface classAno{
    String value(a);
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface methodAno{
    String name(a);
    String type(a);
    int length(a);
}
Copy the code

Execution Result:

V. Summary:

Look at the first time may be a little muddled, more than a few times to deepen understanding! More use in the actual project, look at the bottom of the framework to strengthen their understanding, Rome was not built in a day, have a general understanding and impression can be! Later in the actual gradually strengthen the understanding, so as to be able to digest!


I see no ending, but I will search high and low

If you think I blogger writes good! Writing is not easy, please like, follow, comment to encourage the blogger ~hahah