Reflection mechanism of advanced Java

1> Basis of reflection mechanism

1.1 function of reflection mechanism

	adopt java The reflection mechanism in the language can manipulate bytecode files.
	The advantages are similar to hackers. (bytecode files can be read and modified.)
	Code fragments can be manipulated through reflection mechanism. ( class File.)

1.2 related classes of reflection mechanism

		java.lang.reflect.*;

1.3 important classes of reflection mechanism

  • java.lang.Class: represents the whole bytecode, one type and the whole class.
  • java.lang.reflect.Method: represents the method bytecode in bytecode. Represents a method in a class.
  • java.lang.reflect.Constructor: represents the construction method in bytecode. Construction methods in representative classes
  • java.lang.reflect.Field: represents the attribute bytecode in bytecode. Represents the member variables in the class (static variables + instance variables).
java.lang.Class: 
			public class User{
				// Field
				int no;

				// Constructor
				public User(){
				
				}
				public User(int no){
					this.no = no;
				}

				// Method
				public void setNo(int no){
					this.no = no;
				}
				public int getNo(){
					return no;
				}
			}

2> Three ways to get Class in Java

	First:	 
		Class c = Class.forName("Full class name");
		//Package name Class name
	Second:
		Class c = object.getClass();
	Third:
		Class c = int.class;
		Class c = String.class;
//The first way
c1 = Class.forName("java.lang.String");
 // c1 stands for String Class file, or c1 represents String type.
c2 = Class.forName("java.util.Date"); 
// c2 stands for Date type
Class c3 = Class.forName("java.lang.Integer"); 
// c3 stands for Integer type
Class c4 = Class.forName("java.lang.System");
// c4 stands for System type
//The second way
 String s = "abc";
 Class x = s.getClass();
// x stands for String Class bytecode file, x represents String type.
// Third, any type in the java language, including basic data types, has class attribute.
Class z = String.class; // z stands for String type
Class k = Date.class; // k stands for Date type
Class f = int.class; // f stands for int type
Class e = double.class; // e stands for double type

3> About class loader (understand, do not need to master)

3.1. What is a class loader?

Commands specifically responsible for loading classes/Tools.
ClassLoader

3.2 three class loaders of JDK

  • Start class loader: rt.jar
  • Extension class loader: ext / * jar
  • Application class loader: classpath

3.3. Examples of class loaders

	Suppose there is such a code:
	String s = "abc";
	
	Before the code starts executing, all the required classes will be loaded into the JVM among.
	Load through the class loader. When you see the above code, the class loader will find String.class
	File, find and load, then how to load it?

	First, load through the "start class loader".
		Note: the boot class loader loads specifically: C:\Program Files\Java\jdk1.8.0_101\jre\lib\rt.jar
		rt.jar All of them JDK The core class library.
		
	If it cannot be loaded through the "startup class loader",
		Will pass"extensions class loader "load.
		Note: the extension class loader is specially loaded: C:\Program Files\Java\jdk1.8.0_101\jre\lib\ext\*.jar


	If the extension class loader is not loaded into the
	Will be loaded through the application class loader.
	Note: the application class loader is specially loaded: classpath Class in.

	java In order to ensure the security of class loading, the two parent delegation mechanism is used.
	Priority is given to loading from the boot class loader, which is called "parent"
	"The parent cannot be loaded into, and then loaded from the extension class loader,
	This is called "mother". Parental delegation. If they can't be loaded,
	Will consider loading from the application class loader. Until loaded
	So far.

3.4. Use the class loading mechanism to call static code blocks

package com.bjpowernode.java.reflect;
/*
Study: class What happened to forname()?
    Remember, key points:
        If you just want the static code block of a class to execute, and no other code will execute,
        You can use:
            Class.forName("Full class name "");
        The execution of this method will lead to class loading. When the class is loaded, the static code block will be executed.

Tips:
    We still need JDBC technology later.
 */
public class ReflectTest04 {
    public static void main(String[] args) {
        try {
            // Class. The execution of the forname () method will result in: class loading.
            Class.forName("com.bjpowernode.java.reflect.MyClass");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
public class MyClass {
    // Static code blocks are executed when the class is loaded and only once.
    static {
        System.out.println("MyClass The static code block of class has been executed!");
    }
}

4> Create objects using reflection mechanism

package com.bjpowernode.java.reflect;
import com.bjpowernode.java.bean.User;

/*
What can I do if I get Class?
    Instantiate the object through the newInstance() method of Class.
    Note: the parameterless construction method is actually called inside the newInstance() method, and the parameterless construction must be guaranteed to exist.
 */
public class ReflectTest02 {
    public static void main(String[] args) {

        // This is to create objects without using the reflection mechanism
        User user = new User();
        System.out.println(user);

        // The following code creates objects in the way of reflection mechanism.
        try {
            // Get the Class through the reflection mechanism, and instantiate the object through the Class
            Class c = Class.forName("com.bjpowernode.java.bean.User"); // c stands for User type.
            // The newInstance() method will call the parameterless construction method of the User class to complete the creation of the object.
            // The key point is: newInstance() calls a parameterless structure, and it must be ensured that the parameterless structure exists!
            Object obj = c.newInstance();

            System.out.println(obj); // com.bjpowernode.java.bean.User@10f87f48
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

5> The difference between creating objects by reflection mechanism and ordinary instantiation

5.1. Simple examples

  • Use the IO stream to get value through key in Properties
  • And instantiate the class corresponding to value according to the value of value
package com03;

import java.io.FileReader;
import java.util.Properties;

/*
Verify the flexibility of reflection mechanism.
    java Write the code again, and you can instantiate different objects without changing the java source code.
    Very flexible. (comply with the OCP opening and closing principle: open to expansion and close to modification.)

In the later stage, we need to learn the high-level framework, and in the process of work, we also use the high-level framework,
Including: SSH and SSM
    Spring SpringMVC MyBatis
    Spring Struts Hibernate
    ...
    The underlying implementation principle of these high-level frameworks: reflection mechanism is adopted. So the reflection mechanism is still important.
    Learning the reflection mechanism is helpful for you to understand and analyze the source code at the bottom of the framework.
 */
 class Test {
    public static void main(String[] args) throws Exception{

        // In this way, the code is written dead. Only one object of type User can be created
        //User user = new User();

        // The following code is flexible. The code does not need to be changed. You can modify the configuration file. After the configuration file is modified, you can create different instance objects.
        // Read classInfo. Through IO stream Properties file
        FileReader reader = new FileReader("classinfo2.properties");
        // Create attribute class object Map
        Properties pro = new Properties(); // Both key and value are strings
        // load
        pro.load(reader);
        // Close flow
        reader.close();

        // Get value through key
        String className = pro.getProperty("className");
        //System.out.println(className);

        // Instantiate objects through reflection mechanism
        Class c = Class.forName(className);
        Object obj = c.newInstance();
        //Generics can also be used in this place
        //Class<User> c = (Class<User>)Class.forName(className);
        User obj = c.newInstance(); 
        System.out.println(obj);
    }
}
package com03;

public class User {
    public User(){
        System.out.println("No construction method!");
    }
    // The construction method with parameters is defined, and the construction method without parameters is gone.
    public User(String s){
    }
}
//classinfo2.properties
className = com03.User

5.2. Path problem

package com.bjpowernode.java.reflect;

import java.io.FileReader;

/*
Study the problem of file path.
How to get the absolute path of a file. This method explained below is general. But the premise is: the file needs to be in the classpath. In this way.
 */
public class AboutPath {
    public static void main(String[] args) throws Exception{
        // The disadvantage of this method is poor portability. The default current path in IDEA is the root of project.
        // This code assumes that if you leave the IDEA and change to another location, the current path may not be the root of the project. At this time, this path is invalid.
        //FileReader reader = new FileReader("chapter25/classinfo2.properties");

        // Next, let's talk about a more general path. Even if the code changes location, such writing is still common.
        // Note: the premise of using the following general method is that this file must be in the classpath.
        // What kind of path? All methods under src are under classpath. [remember it]
        // src is the root path of the class.
        /*
        Explanation:
            Thread.currentThread() Current thread object
            getContextClassLoader() Is the method of the thread object, which can get the classloader object of the current thread.
            getResource() [Get resources] this is the method of the classloader object. The classloader of the current thread loads resources from the root path of the class by default.
         */
        String path = Thread.currentThread().getContextClassLoader()
                .getResource("classinfo2.properties").getPath(); // It is common to obtain the absolute path of the file in this way.

        // Using the above code, you can get the absolute path of a file.
        // /C:/Users/Administrator/IdeaProjects/javase/out/production/chapter25/classinfo2.properties
        System.out.println(path);

        // Get dB Absolute path of the properties file (starting from the root path of the class)
        String path2 = Thread.currentThread().getContextClassLoader()
                .getResource("com/bjpowernode/java/bean/db.properties").getPath();
        System.out.println(path2);

    }
}

5.3 resource configuration file

package com.bjpowernode.java.reflect;

import java.util.ResourceBundle;

/*
java.util A resource binder is provided under the package to obtain the content in the attribute configuration file.
When using this method, the property configuration file XXX Properties must be placed under the classpath.
 */
public class ResourceBundleTest {
    public static void main(String[] args) {

        // Resource binders can only bind XXX Properties file. And this file must be in the classpath. The file extension must also be properties
        //The class path starts under module
        //And when writing the path, the extension behind the path cannot be written.
        //ResourceBundle bundle = ResourceBundle.getBundle("classinfo2");
        //classinfo2 file is at the same level as src

        ResourceBundle bundle = ResourceBundle.getBundle("com/bjpowernode/java/bean/db");
        //Under src is the root path of the class. Omit src

        String className = bundle.getString("className");
        System.out.println(className);
    }
}

5.4. Get better code according to the path problem

package com.bjpowernode.java.reflect;

import java.io.FileReader;
import java.io.InputStream;
import java.util.Properties;

public class IoPropertiesTest {
    public static void main(String[] args) throws Exception{

        // Get the absolute path of a file!!!!!
        /*String path = Thread.currentThread().getContextClassLoader()
                .getResource("classinfo2.properties").getPath();
        FileReader reader = new FileReader(path);*/

        // Returns directly as a stream.
        InputStream reader = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("classinfo2.properties");

        Properties pro = new Properties();
        pro.load(reader);
        reader.close();
        // Get value through key
        String className = pro.getProperty("className");
        System.out.println(className);
    }
}

6> Important classes of reflection methods and important methods

  • java.lang.Class: represents the whole bytecode, one type and the whole class.
  • java.lang.reflect.Method: represents the method bytecode in bytecode. Represents a method in a class.
  • java.lang.reflect.Constructor: represents the construction method in bytecode. Construction methods in representative classes
  • java.lang.reflect.Field: represents the attribute bytecode in bytecode. Represents the member variables in the class (static variables + instance variables).

6.1 Class

  • public String getName() gets the full name of the class (package. Class)
  • public String getSimpleName() gets the class name (class)
  • public Field[] getFields() get all fields (properties) decorated with public
  • Public field [] getdeclaraedfields() get all fields (regardless of modifiers)
  • Public Field getdeclaraedfield (string s) gets the Field according to the attribute name
  • public Method[] getDeclaredMethods() get all methods
  • Public method getdeclaredmethod (string name, class <? >... parameterTypes) obtains the method according to the method name and parameter type
        // Get the entire class
        Class studentClass = Class.forName("com.bjpowernode.java.bean.Student");
        //com.bjpowernode.java.bean.Student
        String className = studentClass.getName();
        System.out.println("Full class name:" + className);

        String simpleName = studentClass.getSimpleName();
        System.out.println("Short class name:" + simpleName);

6.2 Field class

  • public String getName() gets the name of the member
  • public int getModifiers() get modifier number ()
  • public Class<?> Gettype() gets the type of Field
  • public int getModifiers() gets the Field modifier code
  • The static method public static void toString(int i) in Modifier converts the Modifier code to String type
        // Gets the Field of all public modifiers in the class
        Field[] fields = studentClass.getFields();
        System.out.println(fields.length); // There is only 1 element in the test array
        // Take out this Field
        Field f = fields[0];
        // Take out the Field and its name
        String fieldName = f.getName();
        System.out.println(fieldName);

        // Get all fields
        Field[] fs = studentClass.getDeclaredFields();
        System.out.println(fs.length); // 4

        System.out.println("==================================");
        // ergodic
        for(Field field : fs){
            // Gets the list of modifiers for the property
            int i = field.getModifiers(); // The returned modifier is a number, and each number is the code of the modifier!!!
            System.out.println(i);
            // Can this "code" number be converted into a "string"?
            String modifierString = Modifier.toString(i);
            System.out.println(modifierString);
            // Gets the type of the property
            Class fieldType = field.getType();
            //String fName = fieldType.getName();
            String fName = fieldType.getSimpleName();
            System.out.println(fName);
            // Gets the name of the property
            System.out.println(field.getName());

6.2.1. Access and modify the properties of the class

  • Access and modify the properties of a class
  • public void set(Object obj, Object value) assigns value to the Field of obj object
  • public Object get(Object obj) gets the attribute value of Field
  • public void setAccessible(boolean flag) breaks the encapsulation and can assign values to private modified attributes
    public static void main(String[] args) throws Exception{

        // How can we access the properties of an object without using the reflection mechanism?
        Student s = new Student();

        // Assign values to attributes
        s.no = 1111; //Three elements: assign 1111 to the no attribute of s object
        //Element 1: object s
        //Element 2: no attribute
        //Element 3:1111

        // Read attribute value
        // Two elements: get the value of the no attribute of the s object.
        System.out.println(s.no);

        // Using reflection mechanism, how to access the properties of an object. (set get)
        Class studentClass = Class.forName("com.bjpowernode.java.bean.Student");
        Object obj = studentClass.newInstance(); // obj is the Student object. (the bottom layer calls the parameterless construction method)

        // Get no attribute (get Field according to the name of the attribute)
        Field noFiled = studentClass.getDeclaredField("no");

        // Assign a value to the no attribute of the obj object (Student object)
        /*
        Although the reflection mechanism is used, three elements are indispensable:
            Element 1: obj object
            Element 2: no attribute
            Element 3: 2222 value
        Note: the reflection mechanism complicates the code, but it's worth it for a "flexibility".
         */
        noFiled.set(obj, 22222); // Assign 2222 to the no attribute of obj object

        // Read the value of the property
        // Two elements: get the value of no attribute of obj object.
        System.out.println(noFiled.get(obj));

        // Can I access private properties?
        Field nameField = studentClass.getDeclaredField("name");

        // Breaking encapsulation (disadvantage of reflection mechanism: breaking encapsulation may leave opportunities for criminals!!!)
        // After this setting, private can also be accessed externally.
        nameField.setAccessible(true);

        // Assign a value to the name attribute
        nameField.set(obj, "jackson");
        // Gets the value of the name attribute
        System.out.println(nameField.get(obj));
    }

6.3. Method class

  • public int getModifiers() get modifier code
  • public String getName() gets the method name
  • public Class<?> [] getparametertypes() get all parameter types
  • public Class<?> Getreturntype() gets the type of the return value of the method
  • The static method public static void toString(int i) in Modifier converts the Field Modifier code to String type
    public static void main(String[] args) throws Exception{
        // Get class
        Class userServiceClass = Class.forName("com.bjpowernode.java.service.UserService");

        // Get all methods (including private ones!)
        Method[] methods = userServiceClass.getDeclaredMethods();
        //System.out.println(methods.length); // 2

        // Traversal Method
        for(Method method : methods){
            // Get modifier list
            System.out.println(Modifier.toString(method.getModifiers()));
            // Gets the return value type of the method
            System.out.println(method.getReturnType().getSimpleName());
            // Get method name
            System.out.println(method.getName());
            // List of modifiers for a method (there may be multiple parameters for a method.)
            Class[] parameterTypes = method.getParameterTypes();
            for(Class parameterType : parameterTypes){
                System.out.println(parameterType.getSimpleName());
            }
        }
    }

6.3.1 calling methods through reflection mechanism

  • public Object invoke(Object obj, Object... args) passes parameters to the method method of obj object
package com.bjpowernode.java.reflect;

import com.bjpowernode.java.service.UserService;

import java.lang.reflect.Method;

/*
Key point: you must master how to call an object's method through the reflection mechanism?
    Five stars*****

    The reflection mechanism makes the code universal, and the changeable contents are written into the configuration file,
    After modifying the configuration file in the future, the objects created and the methods called will be different,
    But the java code doesn't need to be changed. This is the charm of reflection mechanism.
 */
public class ReflectTest10 {
    public static void main(String[] args) throws Exception{
        // How to call a method without using reflection mechanism
        // create object
        UserService userService = new UserService();
        // Call method
        /*
        Element analysis:
            Element 1: userService object
            Element 2: login method name
            Element 3: argument list
            Element 4: return value
         */
        boolean loginSuccess = userService.login("admin","123");
        //System.out.println(loginSuccess);
        System.out.println(loginSuccess ? "Login successful" : "Login failed");

        // How to use reflection mechanism to call the method of an object?
        Class userServiceClass = Class.forName("com.bjpowernode.java.service.UserService");
        // create object
        Object obj = userServiceClass.newInstance();
        // Get Method
        Method loginMethod = userServiceClass.getDeclaredMethod("login", String.class, String.class);
        //Method loginMethod = userServiceClass.getDeclaredMethod("login", int.class);
        // Call method
        // How many elements are there in calling a method? Four elements are also required.
        // One of the most important methods of reflection mechanism must be remembered.
        /*
        Four elements:
        loginMethod method
        obj object
        "admin","123" Argument
        retValue Return value
         */
        Object retValue = loginMethod.invoke(obj, "admin","123123");
        System.out.println(retValue);
    }
}
package com.bjpowernode.java.service;

/**
 * User business class
 */
public class UserService {

    /**
     * Login method
     * @param name user name
     * @param password password
     * @return true Indicates login success, false indicates login failure!
     */
    public boolean login(String name,String password){
        if("admin".equals(name) && "123".equals(password)){
            return true;
        }
        return false;
    }

    // There may also be a login method with the same name
    // How to distinguish a method in java depends on the method name and parameter list.
    public void login(int i){

    }

    /**
     * Method of exiting the system
     */
    public void logout(){
        System.out.println("The system has exited safely!");
    }
}

Tags: Java Class reflection JavaSE

Posted by yellowepi on Sun, 10 Apr 2022 23:47:56 +0300