[Java foundation] reflection mechanism summary

introduction

When I first learned Java reflection mechanism, I just felt very magical, but I didn't know how to use it, so I forgot it after a period of time; Recently, I came into contact with the framework, encountered reflection in my study, and deeply realized the magic of the reflection mechanism. I came back to review the reflection mechanism and write a small summary;

concept

What is the reflection mechanism? Baidu Encyclopedia well explains:

Java's reflection mechanism means that in the running state of the program, you can construct the object of any class, understand the class to which any object belongs, understand the member variables and methods of any class, and call the properties and methods of any object.
This function of dynamically obtaining program information and dynamically calling objects is called the reflection mechanism of Java language. Reflection is regarded as the key to dynamic language.

I won't elaborate on the concept here. You can gradually understand it in use;

Let me show you the basic operation of Java reflection mechanism;
Note: in order to make the code concise and easy to see, all Exception handling directly throw an Exception (don't do this in practical applications!!)

Get type

In Java, there is a type called Class, which is a kind of type and has the same meaning as String and Object, so don't confuse it with Class;

We can obtain the type of a Class through the reflection mechanism, and the return value type is Class

There are three ways to get types:

  • Class static method forName()
  • Object getClass
  • Class name class

The following is a code demonstration:

// There are three ways to obtain different types (classes): class static method forName and object getClass(), class name class
// Class is also a class type, just like String and Object
// java.lang.Class: Class represents the entire bytecode, represents a type, and represents the entire Class
public class ReflectTest01 {
    public static void main(String[] args) throws Exception {

        // The first is to obtain the Class type through the static method of Class: forName
        Class c1 = Class.forName("java.lang.String"); // String type
        Class c2 = Class.forName("java.lang.Object"); // Object type
        System.out.println(c1 == c2); // String type is different from Object type, false
        //==============================================================

        // Second: (object. getClass()) any object in java has this method: getClass(), and the return value type is Class type
        Class c3 = "444".getClass(); // c5 is a String type
        Class c4 = new Object().getClass(); // c6 is the Object type
        System.out.println(c1 == c3); // true
        System.out.println(c2 == c4); // true
        //=========================================================

        // Third: (class name. Class) any type in java, including basic data types, has one Class attribute
        Class c5 = String.class; // String type
        Class c6 = Object.class; // Object type
        System.out.println(c1 == c5); // true
        System.out.println(c2 == c6); // true
    }
}

The first of the three methods is mainly noted. The usage rules of the forName() method are:

Remember that the forName() method can make the corresponding class load, and the class load will execute the static code block;
So if you only want to execute static code blocks, you can use the forName() method;
Why do you say that? Because this will be used in the JDBC registration driver;

Let's show this feature:
Class passed in by forName():

public class MyClass {
    static {
        System.out.println("Static code block executed!!");
    }
}
// Conclusion: if you only want the static code block of one class to be executed, and the rest of the code is not executed, you can use:
// Class.forName("full class name")
// The execution of this method will lead to class loading, and the static code will be executed quickly when the class is loaded
// *****This will be used later in JDBC*****
public class ReflectTest03 {
    public static void main(String[] args) throws Exception{
        // Class.forName() causes the class to load and the static code to execute quickly
        Class.forName("reflect.test03.MyClass");

    }
}

Output:

Of course, this is just a simple simulation, but the principle is the same;
Conclusion: if you only want the static code block of one class to be executed, and the rest of the code is not executed, you can use: class Forname ("full class name")

Instantiate object

After obtaining the object type, you can instantiate the corresponding object through the type, using the newInstance() method

In the framework, it is generally necessary to obtain and operate the content of the configuration file through the reflection mechanism. Different information can be obtained through the content of the configuration file. Here is a demonstration of how to instantiate an object through the configuration file;
Note: used here properties file, easy to understand

Create a properties file:

This configuration file needs to be placed in the directory of the project, not in the classpath (src) or other directories;

import java.io.FileInputStream;
import java.util.Properties;

// Obtain the content of the configuration file and instantiate the object through the reflection mechanism
// The reflection mechanism makes the program more flexible and conforms to the OPC opening and closing principle
// The underlying principles of high-level frameworks (Spring, etc.) are reflection mechanisms
public class ReflectTest02 {
    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("classname.properties"); // Create input stream
        Properties properties = new Properties(); // The underlying implementation is Map, which inherits HashTable. Both key and Value are String types
        properties.load(fis); // Load the Java configuration file classname Properties into memory
        fis.close(); // Close input stream

        String classname = properties.getProperty("first"); // Get Value through key
        Class<?> clazz = Class.forName(classname); // Gets the type of classname (Value)
        Object obj = clazz.newInstance(); // Create object instance
        System.out.println(obj);
    }
}

Because the key passed in here is first, the output is:

You can see that an Object object is instantiated

There is another method, which is a relatively common and simple method:
java. A resource binder is provided under the util package to obtain the content in the attribute configuration file;

Two methods of this class are required:

Create a profile:

When using this method, the configuration file must be placed under the classpath (src)

import java.util.ResourceBundle;

// When using the following method, the property configuration file XXX Properties must be placed under the classpath.
// It implements the same functions as ReflectTest02, but uses a new method to obtain the absolute path, which is commonly used in the future
public class ReflectTest05 {
    public static void main(String[] args) throws Exception {
        // Resource binders can only bind XXX Properties file. And this file must be in the classpath (src folder). The file extension must also be properties
        // And when writing the path, the extension after the path properties cannot be written.
        ResourceBundle bundle = ResourceBundle.getBundle("absolute_path"); // Binding profile
        String classname = bundle.getString("second"); // Get Value through key
        Class c = Class.forName(classname);
        Object obj = c.newInstance();
        System.out.println(obj);
    }
}

This time, the key is passed in as second, and the output is:

Some operations of reflection mechanism

The following shows some operations of the reflection mechanism, which are actually the calls of various methods. Just check the documents;
Here, first define a class. All the following operations are based on this class;

public class TestClass01 {
    int age;
    public String name;
    private final static int num = 4;
    static protected boolean flag;

    public void firstMethod(String s) {
        System.out.println("Call of the first method!");
    }
    public void secondMethod(String s, int i) {
        System.out.println("Call of the second method!");
    }
}

Reflect all fields in the TestClass class (properties)

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class ReflectTest06 {
    public static void main(String[] args) throws Exception {
        // Get the entire class
        Class testClass = Class.forName("reflect.test06.TestClass01");

        // Get class name
        String classname = testClass.getName(); // Full class name
        System.out.println(classname);
        System.out.println(testClass.getSimpleName()); // Simple class name

        // Gets the properties of the TestClass class
        // getFields() will only get all public decorated properties
        Field[] fields01 = testClass.getFields();
        Field f = fields01[0];
        String filename = f.getName(); // Get property name
        System.out.println(filename);

        System.out.println("=====================");

        // Get all properties
        Field[] fields02 = testClass.getDeclaredFields();
        for (Field i : fields02) {
            System.out.println(i.getName()); // Get property name
            // Gets the type of the property
            System.out.println(i.getType().getName()); // Complete type
            System.out.println(i.getType().getSimpleName()); // Simple type
            // Get Modifier (using the toString method of Modifier class)
            System.out.println(Modifier.toString(i.getModifiers()));
            System.out.println("------------");
        }
    }
}

Output:

reflect.test06.TestClass01
TestClass01
name
=====================
age
int
int

------------
name
java.lang.String
String
public
------------
num
int
int
private static final
------------
flag
boolean
boolean
protected static
------------

Gets the value in the object property

import java.lang.reflect.Field;

public class ReflectTest07 {
    public static void main(String[] args) throws Exception {
        Class className = Class.forName("reflect.test06.TestClass01"); // Get class
        Object obj = className.newInstance(); // Creating objects from classes
        Field ageFiled = className.getDeclaredField("age"); // Get age attribute
        // An instantiated object obj is required to assign a value to an attribute
        ageFiled.set(obj, 111); // Copy 111 to the age attribute of the obj object
        System.out.println(ageFiled.get(obj)); // Gets the value of the age attribute of the obj object
    }
}

Output:

Get method and call (important)

This is relatively important. The getMethod() method or getMethods() method of Class class is used to obtain the method

Return type Method:

Similarly, after obtaining the Method, you need to call a Method of the Method class: invoke()

The following is the specific use method:

import java.lang.reflect.Method;

// Call method through reflection mechanism
public class ReflectTest08 {
    public static void main(String[] args) throws Exception{
        // Get class first
        Class c = Class.forName("reflect.test06.TestClass01");
        // Instantiate objects through classes
        Object obj = c.newInstance();
        // Get method through class
        Method method01 = c.getMethod("firstMethod", String.class);
        Method method02 = c.getMethod("secondMethod", String.class, int.class);

        // Called by the method obtained (via the invoke method)
        // Requirements: 1. This method; 2. An object; 3. Corresponding parameters
        Object retValue01 = method01.invoke(obj, "This is a useless parameter");
        Object retValue02 = method02.invoke(obj, "This is also a useless parameter, and so is the following 1", 1);
    }
}

Output:

summary

These are some basic and common operations of reflection mechanism, but the actual application will not be so simple, so we must master the basic so that we can understand and learn the underlying source code when learning spring and other frameworks in the future;
Welcome your comments!

Keywords: Java Back-end reflection JavaSE

Added by Kitara on Sun, 09 Jan 2022 04:49:53 +0200