preface

Just to summarize, we learned about reflex mechanism a while ago.

Java files are compiled to generate bytecode files (.class files), and the JVM loads the bytecode files to execute the runtime.

The first two steps (compile phase) are done on hard disk, the last step (run phase) is done in memory, and the intermediate link is: The JVM uses the —-ClassLoader to load a class file from the hard disk into memory to generate an object of the class class that can use its member variables and methods. A Class is loaded only once by default, so there is one and only one Class object for this Class.

What is Java reflection?

In 1983, Smith first proposed the concept of reflection, which mainly refers to the ability of a program to access, detect and modify its own state or behavior.

The Java reflection mechanism dissects classes and manipulates constructors, member methods, and member attributes (mainly used in frameworks) in the runtime state. This function of dynamically retrieving information and dynamically calling methods of objects is called the Reflection mechanism of the Java language.

Class object and reflection mechanism.

Now that you understand the concept of reflection, you can see that in order to do anything with Java reflection, you need to use Class objects, so Class objects are a prerequisite for reflection.

So, how do I get a Class object?

There are three ways to get a Class object in Java:

  1. The name of the class. The class

  2. The object name. GetClass

  3. Class. ForName (” fully qualified name (package name + Class name) “);

Add: There are two types of Class objects

1. Plain Class objects: based on the reference type

2. Predefined (in the JVM)Class objects: based on primitive types and void

Several functions of reflex mechanism:

  1. Determine the class to which any object belongs at run time
  2. Constructs an object of any class at run time
  3. Determine which member variables and methods any class has at run time
  4. Call a method of any object at run time

Prepare a class:

package com.test.demo;

public class Student {
    public String name;
    private int age;

    public Student(a) {}private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void show(String msg){
        System.out.println("Show method =" + msg);
    }
    private void speak(String msg,int number){
        System.out.println("Speak method =" + msg +":"+ number );
    }

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

Use of reflection 1: Reflection from the Constructor

Again, we could construct a new Student from a public empty parameter, but we could not new a private full parameter construct.

Student student = new Student();
Copy the code

Now reflection constructors (create instance in reflection form)

public static void main(String[] args)
            throws NoSuchMethodException, IllegalAccessException,
            InvocationTargetException, InstantiationException {
        // Get the Class objectClass<? > clazz = Student.class;/* The corresponding constructor parameter type is parameter type */Constructor<? > constructor = clazz.getConstructor();/* Create instance parameter type is argument type (parameter 1 corresponds to parameter 1) */
        Object obj = constructor.newInstance();
        System.out.println("obj = " + obj);
}
Copy the code

The Student object obtained in this way has the same effect as the object produced by the empty parameter constructor new (the actual business development is not meaningful).

The former is created by new in a more passive way than the former is created by reflection, while the former is created by reflection itself, so the constructor is the reverse.

Alternatively, you can create the constructor directly from the Class object:

public static void main(String[] args)
            throws  IllegalAccessException, InstantiationException {
        // Get the Class objectClass<? > clazz = Student.class;/* The default call to the null argument constructor to create an instance is obsolete in JDk9 */
        Object obj = clazz.newInstance();
        System.out.println("obj = " + obj);
    }
Copy the code

There is also a private constructor in the Student class, which normally does not create objects. But reflection can do:

public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {// Get the Class object Class<? > clazz = Student.class; GetConstructor (): getDeclaredConstructor(): getDeclaredConstructor(): getDeclaredConstructor(); */ Constructor<? > constructor = clazz.getDeclaredConstructor(String.class, int.class); System.out.println("Full parameter private construct:"+ constructor); / * private structure and newInstance produces illegal access exception: Java. Lang. IllegalAccessException so to change the permissionssetAccessible () - > violence reflected * / constructor. SetAccessible (true);
       Object obj = constructor.newInstance("Xiao Ming", 20); System.out.println("obj = " + obj);
    }
Copy the code

That’s how reflection is used to create an object (reflection constructor).

Use of reflection 2: reflection of Method

Next look at the reflection of the two methods in the Student object

Our previous (external) use of methods was to call (non-private) methods from objects, or directly from the class if it was static.

So what do YOU do with a reflection call (non-private) method?

public static void main(String[] args)
            throws NoSuchMethodException, IllegalAccessException,
            InvocationTargetException {
        // Get the Class object
        Student student = new Student();
        Class<? extends Student> clazz = student.getClass();
        /* getMethod(): getMethod(): getMethod(): getMethod()
        Method show = clazz.getMethod("show", String.class);
        /* The show method is called with an object and arguments. The invoke() method is called with an argument */
        show.invoke(student, "hello public show");
    }
Copy the code

Reflection can be understood as the grammatical inversion of a language:

We usually write code that I (object) call method, here is:

New Student().show(” object calls method “);

Invoke (student, “Hello public show”); ,

The show method takes into account who’s calling me, and then the Student object says, I’m calling you (Student as argument).

Extension: If the static keyword is added to a public show method, does it affect the method call?

Tip: Static has nothing to do with objects.

Invoke (student, “Hello public show”); invoke(student,” Hello public show”); It does not matter if the 1 argument is null, because the show method comes from the Student Class object.

Now how is reflection of a private method implemented?

Ps: The reflection channel API is very regular and readable

public static void main(String[] args)
            throws NoSuchMethodException, IllegalAccessException,
            InvocationTargetException {
         // Get the Class object
        Student student = new Student();
        Class<? extends Student> clazz = student.getClass();
        /* getDeclaredMethod(): getDeclaredMethod(): getDeclaredMethod(): getDeclaredMethod(): getDeclaredMethod(): getDeclaredMethod(
        Method speak = clazz.getDeclaredMethod("speak", String.class, int.class);
        // Private method, violent reflection
        speak.setAccessible(true);
        /* The show method is called with an object and arguments. The invoke() method is called with an argument */
        speak.invoke(student, "hello private speak".2018);
    }
Copy the code

Use of reflection 3: Reflection of property (Field)

Student entity has a common property and a private property, we can set the value of the common property by object, so how do we assign all the properties by reflection?

Let’s first look at the assignment of the common attribute name

public static void main(String[] args)
            throws ClassNotFoundException, NoSuchFieldException,
            IllegalAccessException, InstantiationException {
         // Get the Class object with a fully qualified nameClass<? > clazz = Class.forName("com.test.demo.Student");
        /* getField(): Get the attribute */ by the attribute name
        Field name = clazz.getField("name");
        // Get the object
        Object obj = clazz.newInstance();
        /* Sets a value. Parameter 1: which object is the property value. Parameter 2: Parameter */
        name.set(obj,"Zhang");
        System.out.println(obj);
    }
Copy the code

The reflection properties are not difficult to understand based on the API described earlier.

Reflection of private attributes is also not difficult to implement

public static void main(String[] args)
            throws ClassNotFoundException, NoSuchFieldException,
            IllegalAccessException, InstantiationException {
         // Get the Class object with a fully qualified nameClass<? > clazz = Class.forName("com.test.demo.Student");
        /* getDeclaredField(): Get the (all permissions) property */
        Field age = clazz.getDeclaredField("age");
        // Violent reflex
        age.setAccessible(true);
        // Create an object
        Object obj = clazz.newInstance();
        /* Sets a value. Parameter 1: which object is the property value. Parameter 2: Parameter */
        age.set(obj,20);
        System.out.println(obj);
    }
Copy the code

Conclusion:

To use Java’s reflection mechanism, there are three general steps to follow:

  1. Get the Class object you want to operate on
  2. Get the method or property name of the operation Class from the Class object obtained in the first step
  3. The method or property obtained in step 2

So what does reflection do?

Reflection is mainly used in the framework, understanding reflection (more than reflection) to better understand some of the principles of the framework.