Learn JAVA reflection learning together (super detailed)

Posted by ghjr on Wed, 29 Dec 2021 17:03:40 +0100

1 what is reflection?


Reflection is one of the features of Java programming language. It allows running Java programs to check themselves, or "self-examination", also known as "introspection".
Reflection is so powerful that it can even directly manipulate the private properties of the program. We all learned a concept earlier. Resources encapsulated by private can only be accessed inside the class, but not outside. However, this provision is completely broken by reflection.
Reflection is like a mirror. It can get all the information of a class at run time, get any defined information (including member variables, member methods, constructors, etc.), and manipulate the fields, methods, constructors, etc. of the class.

2 why reflection?

If you want to create an object, we can directly new User(); It's not very convenient. Why create objects through reflection?

Then I'll ask you a question first. Why do you go to a restaurant?
For example: we want to have a steak dinner. If we create it ourselves, we have to manage everything.
The advantage is that I'm very clear about what to do at every step, and the disadvantage is that I have to realize everything by myself. It's not dead tired. Cow delivery you tube, eat you tube, slaughter you tube, transport you tube, refrigerate you tube, cook you tube, serve you tube. Take cooking as an example. Can you have a top chef do it well?
Then what shall I do? There is a saying that professional things are done by professional people, raised by farmers, slaughtered by executioners, and cooked by special chefs. What are we doing?
Let's just cross our legs and bring it directly to eat.
Moreover, the restaurant should not throw things on the ground. Let's pick them up and eat. They are not all primitive people. Then what shall I do? It's very simple. Put the prepared things in a container, such as steak on a plate.

In the later study, we will learn about the framework. One framework, Spring, is a very professional and powerful product, which can help us create and manage objects. In the future, I can get the new object directly from the Beans in the container provided by Spring without manually. The bottom layer of Beans is actually a map < string, Object >, which is finally obtained through getBean("user"). The core implementation is the use of reflection technology.

To sum up, the class is not created by you, but by your colleagues or directly by a third-party company. At this time, if you want to call the underlying functions of this class, you need to implement reflection technology. It's a little abstract. Don't worry. Let's make a case and you'll be clear immediately.

3. API required for reflection


3.1 get bytecode object

Class.forName("full path of class");

Class name class

Object getClass();

3.2 common methods


Get package name class name
clazz.getPackage().getName() / / package name
clazz.getSimpleName() / / class name
clazz.getName() / / full class name

Get member variable definition information
getFields() / / get all exposed member variables, including inheritance variables
Getdeclaraedfields() / / get the member variables defined by this class, including private variables but excluding inherited variables
Getfield (variable name)
Getdeclaraedfield (variable name)

Get construction method definition information
Getconstructor (parameter type list) / / get the exposed constructor
getConstructors() / / get all the exposed construction methods
Getdeclaraedconstructors() / / get all construction methods, including private ones
getDeclaredConstructor(int.class,String.class)

Get method definition information
getMethods() / / get all visible methods, including inherited methods
Getmethod (method name, parameter type list)
getDeclaredMethods() / / get the methods defined by this class, including private methods and excluding inherited methods
Getdeclaraedmethod (method name, int.class,String.class)

Reflect new instance
clazz.newInstance();// Execute parameterless construction to create objects
clazz.newInstance(666, "SpongeBob")// Execute parametric construction to create objects
clazz.getConstructor(int.class,String.class) / / get the constructor

Reflection call member variable
clazz. Getdeclaraedfield (variable name)// Get variable
clazz.setAccessible(true);// Allow access to private members
f. Set (instance, value)// Assign a value to the variable of the specified instance, static variable, and the first parameter is null
f. Get (instance)// Access the value of the specified instance variable, static variable, and the first parameter is null

Reflection calls member methods
Method m = Clazz. Getdeclaraedmethod (method name, parameter type list);
m.setAccessible(true);// Allow private methods to be called
m. Invoke (instance, parameter data)// Let the specified instance execute the method

4 Application of reflection

4.1 create: test material class

Create package: CN tedu. reflection
Create class: student java*

package cn.tedu.review;
/*This class is used to review reflective materials*/
public class Student {
    //1. Define member variables
    private String name;
    public int age;

    //2. Provide get and set methods for encapsulated attributes
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    //3. Generate nonparametric and fully parametric structures of this class
    public Student(){}
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //4. Provide common methods for this class
    public void play(){
        System.out.println("Today's finale, I'm going to write 1 after school W Line code play~");
    }
    public void sunDay(int n){
        System.out.println("National Day"+n+"day");
    }
    //5. To view the specific properties and property values of the student object, rewrite toString()
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

4.2 exercise: getting class objects

Create package: CN tedu. reflection
Create class: testreflect java

package cn.tedu.reflection;

import org.junit.Test;

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

/*This class is used for reflection testing*/
public class TestReflect {
    //1. Create the program's entry function main() -- No
    /*Unit test method: it is the smallest test unit in Java. It is flexible to use. Recommendation Index: 5 stars
    * Syntax requirements: @ Test + public + void + no parameters
    * Note: import package is required when using: Add JUnit 4 library to the build path
    * Effect after package Guide: import org junit. Test
    * Execution method: select the green triangle in front of the method name, and there will be a green check mark for successful operation
    * */
    //2. Obtain the bytecode object corresponding to the target class Student through the unit test method
    @Test
    public void getClazz() throws ClassNotFoundException {
        //Practice 3 ways to get bytecode objects
        Class<?> clazz1 = Class.forName("cn.tedu.review.Student");
        Class<?> clazz2 = Student.class;
        Class<?> clazz3 = new Student().getClass();

        //The bytecode object corresponding to the Student class is printed
        System.out.println(clazz1);//class cn.tedu.reflection.Student
        //Gets the name of the current bytecode object clazz1
        System.out.println(clazz1.getName());//cn.tedu.reflection.Student
        //Get the class name of Student class through bytecode object
        System.out.println(clazz2.getSimpleName());
        //Obtain the package object corresponding to the Student class through the bytecode object
        System.out.println(clazz3.getPackage());
        //Through the bytecode object, first obtain the package object corresponding to the Student class, and then obtain the name of the package object
        System.out.println(clazz3.getPackage().getName());
    }

4.3 exercise: getting member variables

package cn.tedu.reflection;

import java.lang.reflect.Field;

import org.junit.Test;

/**This class is used to test reflection*/
public class TestReflect {
	//3. Practice the definition and traversal of reference type array through unit test method
    @Test
    public void getStu() {
        //1. Create three objects of Student class
        Student s1 = new Student("Zhang San", 3);
        Student s2 = new Student("Li Si", 4);
        Student s3 = new Student("Wang Wu", 5);
        //2. Create an array and store the three objects in the array
        Student[] s = {s1, s2, s3};
        //3. Print the array directly and view the elements in the array
        System.out.println(Arrays.toString(s));
        //4. Traverse the student array, get each student object and do further operations
        for (Student stu : s) {
            //System.out.println(stu);
            stu.play();//Execute play() by traversing the object
            System.out.println(stu.age);//Print the age attribute by traversing the object
        }
    }

	//4. Obtain the member variables in the Student class through the unit test method
    @Test
    public void getFie() throws ClassNotFoundException {
        //1. Get bytecode object
        Class<?> clazz = Class.forName("cn.tedu.review.Student");
        //2. Get member variables through bytecode object
        Field[] fs = clazz.getFields();
        //3. Traverse the array to get the specific information of each member variable
        /*be careful! Currently, the modifier of a member variable can only be obtained if it is public. Otherwise, the default modifier cannot be obtained*/
        for(Field f : fs){
            System.out.println(f.getName());//Get the field name through the field object to which this round loops
            System.out.println(f.getType());//Get the type of the field through the field object to which this round loops
        }

    }
}

4.5 exercise: get the construction method of class through bytecode object

package cn.tedu.reflection;

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

import org.junit.Test;

/**This class is used to test reflection*/
public class TestReflect {
    //6. Obtain the construction method in the Student class through the unit test method
    @Test
    public void getCons() {
        //1. Get bytecode object
        Class<?> clazz = new Student().getClass();
        //2. Obtain the construction method of the target class Student through the bytecode object
        Constructor<?>[] cs = clazz.getConstructors();
        //3. Traverse the array through an efficient for loop
        for(Constructor c : cs){
            System.out.println(c.getName());//Print the name of the construction method traversed in this round
            Class[] pt = c.getParameterTypes();//Get the parameter type of the constructor through the constructor object traversed in this round
            System.out.println(Arrays.toString(pt));//Print parameter type
        }
    }

4.6 exercise: creating objects

package cn.tedu.reflection;

import java.lang.reflect.Constructor;

import org.junit.Test;

/**This class is used to test reflection*/
public class TestReflect {
//7. Create the object of the Student target class through the unit test method
    @Test
    public void getObject() throws Exception {
        //1. Get bytecode object
        Class<?> clazz = Student.class;
        //2. Create the object of the target class through reflection technology, and pay attention to throwing exceptions
        /*Reflection object creation scheme 1: create an object by triggering the parameterless construction of the target class*/
        Object o = clazz.newInstance();
        System.out.println(o);//In this step, the object Student{name='null', age=0} has been obtained

        /*Reflection object creation scheme 2: create an object by triggering the full parameter construction of the target class
        * Idea:
        * 1.Get the specified constructor object first. Note that you need to specify the parameters of the constructor. What is passed in is class bytecode object
        * 2.Create the object of the Student target class through the constructor object just obtained, and assign a value to the property of the object
        * */
        //3. Get the full parameter construction specified in the target class
        Constructor<?> c = clazz.getConstructor(String.class, int.class);
        //System.out.println(c);
        //4. Through the obtained constructor: create object + assign value to the attribute of the object
        Object o2 = c.newInstance("Zhao Liu", 6);
        System.out.println(o2);
    }
}

4.7 familiar with API

Create your own class exercise, get all the resources in the class, and be familiar with the API s involved in reflection

5 violent reflex

It refers to that private attributes or methods in the program can be obtained violently through reflection technology. Common methods to use are as follows:

5.1 create: test material class

Create package: CN tedu. reflection
Create class: person java*

package cn.tedu.review;
/*This class is used as material for violent reflection test*/
public class Person {
    //1. Provide private attributes
    private String name;
    private int age;

    //2. Provide private methods
    private void save(int n,String s){
        System.out.println("save()..."+n+s);
    }
    private void update(){
        System.out.println("update()...");
    }
}

 

5.2 exercise: creating a test class

Create package: CN tedu. reflection
Create class: testreflect2 java

package tedu.reflection;

import org.junit.Test;

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

/*This class is used to test violent reflex*/
public class TestReflect2 {
   /*1.Get and manipulate properties through violent reflection*/
    @Test
    public void getFie2() throws Exception {
        //1. Get bytecode object
        Class<?> clazz = Person.class;
        //2. Get the specified private property. The property name is passed in. Note that an exception is thrown
        Field field = clazz.getDeclaredField("name");
        //3. View the attribute information according to the attribute object just obtained
        System.out.println(field);//Print the obtained field object directly
        System.out.println(field.getType().getName());//java.lang.String
        System.out.println(field.getType());//class java.lang.String

        //4. Set the value of the attribute
        //4.1 you need to specify which object's name attribute is set to. If there is no object, create the object
        Object obj = clazz.newInstance();//Trigger parameterless construction to create objects using reflection

        //4.2 violent reflection, private visible permission needs to be set!!!
        field.setAccessible(true);

        //4.3 set the attribute value of the newly created object obj as SpongeBob through the field object
        //field is the name attribute we just obtained
        //set(m,n)--m is the value set for the name attribute of which object, and N is the value set
        field.set(obj,"Spongebob");
        //4.4 print and view the attribute value just set
        //field.get(m)--field represents the name attribute of the Person class. M is the attribute value of which object to view
        System.out.println(field.get(obj));
    }

    //2. Define the unit test method and use violent reflection to operate the private attribute age in the Person class [consolidation exercise]
    @Test
    public void getFie3() throws Exception {
        //1. Get bytecode object
        Class<?> clazz = Person.class;
        //2. Get the specified private property object
        Field f = clazz.getDeclaredField("age");
        //3. View relevant information, such as attribute type, according to the obtained attribute object
        System.out.println(f.getType().getName());
        //4. Operation: set attribute value: three elements are required: what value is set for which attribute [2] of which object [1] [3]
        //4.1 you need to set the value of this age attribute to which object you want to assign first
        Object obj = clazz.newInstance();
        //4.2 before setting the value for the attribute, you need to set the permission private visible, otherwise an error will be reported!
        f.setAccessible(true);
        //4.3 set the value of obj object through the age attribute object just obtained
        f.set(obj,17);
        //4.4 print and check whether the attribute value just set is successful
        System.out.println(f.get(obj));
    }
    /*3.Unit test 2: get and set private methods*/
    @Test
    public void getFunction() throws Exception {
        //1. Get Class bytecode object
        Class<?> clazz = Person.class;
        //2. Methods of obtaining private information through violent reflection
        /*getDeclaredMethod(m,x,y,z...)
        * m:Method name to get
        * x,y,z...Variable parameter is the parameter type of this method, but note that ". class" should be added
        * */
        Method method = clazz.getDeclaredMethod("save",int.class,String.class);
        //3.1 create objects by reflection without objects
        Object obj = clazz.newInstance();
        //3.2 to execute private methods, you also need to set private visibility first
        method.setAccessible(true);
        /*invoke(o,x,y,z...),Represents a method performed by reflection technology
        * o :Which object's method is to be executed
        * x,y,z...:Parameters to be passed in when executing this method [previously obtained save(), represented by method object]
        * */
        //3.3 execute the target method [save()] of the target object obj through the reflection technology invoke()
        //When save() is called, the parameter passed in is 100, "SpongeBob"
        method.invoke(obj,100,"Spongebob");
    }
}

Congratulations, you have learned a new knowledge. There are many reflection API s. You should practice more

Topics: .NET WPF p2p