reflective learning

demand elicitation reflection

  • According to the information specified in the configuration file re.properties, create a Cat object and call the method hi
  • Especially when learning the framework, that is, through external file configuration, without modifying the source code, to control the program, in line with the design OCP principle (open and closed principle: do not modify the source code, expand the function)
classfullpath=com.day02.Cat
method=hi
package com.day02;

public class Cat {
    public Cat() {
    }
    public void hi(){
        System.out.println("Cat of hi method");
    }
}
/**
 * The introduction of reflection problems
 */
@SuppressWarnings({"all"})
public class ReflectionQuestion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException,
            InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//According to the information specified in the configuration file re.properties, create a Cat object and call the method hi

//The traditional way new object -> call method
// Cat cat = new Cat();
// cat.hi(); ===> cat.cry() Modify the source code.
//Let's try to do it -> understand reflection
//1. Using the Properties class, you can read and write configuration files
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();//"com.hspedu.Cat"
        String methodName = properties.get("method").toString();//"hi"
        System.out.println("classfullpath=" + classfullpath);
        System.out.println("method=" + methodName);
//2. Create an object, the traditional method does not work => reflection mechanism
//new classfullpath();
//3. Use reflection mechanism to solve
//(1) Load the class and return the object cls of type Class
        Class cls = Class.forName(classfullpath);
//(2) Get the object instance of the class com.hspedu.Cat you loaded through cls
        Object o = cls.newInstance();
        System.out.println("o type of run=" + o.getClass()); //run type
//(3) Get the method object of the methodName"hi" of the class com.hspedu.Cat you loaded through cls
// That is: in reflection, methods can be treated as objects (everything is an object)
        Method method1 = cls.getMethod(methodName);
//(4) Calling a method through method1: that is, calling a method through a method object
        System.out.println("=============================");
        method1.invoke(o); //traditional method object.method() , reflection mechanism method.invoke( object)
    }
}

reflection mechanism

  • The reflection mechanism allows the program to obtain the internal information of any class (such as member variables, member methods, constructors, etc.) with the help of ReflectionAPl during execution, and can manipulate the properties and methods of the object. Reflection is used in both design patterns and under the hood of frameworks.
  • After the class is loaded, an object of type Class is generated in the heap (a class has only one Class object), which contains the complete structural information of the class. The structure of the class is obtained through this object. This Class object is like a mirror, through which the structure of the class can be seen, so it is called figuratively: reflection

Schematic diagram of Java reflection mechanism

java reflection mechanism can be completed

  • Determine the class to which any object belongs at runtime;
  • Construct an object of any class at runtime;
  • Get member variables and methods of any class at runtime;
  • Call member variables and methods of any object at runtime;
  • Generate dynamic proxy;

Main classes related to reflection

  1. java.lang.Class: represents a class, and the Class object represents the object in the heap after a class is loaded
  2. java.lang.reflect.Method: represents the method of the class, and the Method object represents the method of a class
  3. java.lang.reflect.Field: represents a member variable of a class, and a Field object represents a member variable of a class
  4. java.lang.reflect.Constructor: represents the constructor of the class, and the Constructor object represents the constructor
    These classes are in java.lang.reflection

Reflection Advantages and Disadvantages

  • Advantages: Objects can be dynamically created and used (also the underlying core of the framework), flexible in use, and without reflection mechanism, framework technology loses underlying support.
  • Disadvantages: The use of reflection is basically to explain the execution, which has an impact on the execution speed.

Applications

 * Test the performance of reflection calls, and optimize solutions
 */
public class Reflection02 {
    public
    static
    void
    main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
            InvocationTargetException, InstantiationException, IllegalAccessException {
//Field
//Method
//Constructor
        m1();//Tradition
        m2();//reflection
        m3();//reflection optimization
    }
    //The traditional way to call hi
    public static void m1() {
        Cat cat = new Cat();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000000; i++) {
            cat.hi();
        }
        long end = System.currentTimeMillis();
        System.out.println("m1() time consuming=" + (end - start));
    }
    //The reflection mechanism calls the method hi
    public static void m2() throws ClassNotFoundException, IllegalAccessException, InstantiationException,
            NoSuchMethodException, InvocationTargetException {
        Class cls = Class.forName("com.day02.Cat");
        Object o = cls.newInstance();
        Method hi = cls.getMethod("hi");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000000; i++) {
            hi.invoke(o);//method call reflection
        }
        long end = System.currentTimeMillis();
        System.out.println("m2() time consuming=" + (end - start));
    }
    //Reflection call optimization + turn off access checking
    public static void m3() throws ClassNotFoundException, IllegalAccessException, InstantiationException,
            NoSuchMethodException, InvocationTargetException {
        Class cls = Class.forName("com.qfedu.Cat");
        Object o = cls.newInstance();
        Method hi = cls.getMethod("hi");
        hi.setAccessible(true);//When calling a method by reflection, cancel the access check
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000000; i++) {
            hi.invoke(o);//method call reflection
        }
        long end = System.currentTimeMillis();
        System.out.println("m3() time consuming=" + (end - start));
    }
}

Reflection call optimization - turn off access checking

  • Method and Field, Constructor objects have setAccessible (method
  • setAccessible is a switch to enable and disable access security checks
  • A parameter value of true indicates that the reflected object cancels the access check when it is used, which improves the efficiency of reflection. A parameter value of false indicates that the reflected object performs an access check

Class

  • Class is also a class, so it also inherits the Object class [class diagram]
  • Class objects are not created by new, but created by the system;
    For the Class class object of a certain class, there is only one copy in memory, because the class is loaded only once;
  • Instances of each class remember which Class instance they were generated from
    The complete structure of a class can be completely obtained through the Class object, through a series of API s
  • Class objects are stored on the heap
  • The bytecode binary data of the class is placed in the method area, and some places are called class metadata (including method code, variable name, method name, access rights, etc.)

Common methods of the Class class

method nameFunction Description
static Class forName(String name)Returns the Class object with the specified class name name
Object newInstance()Call the default constructor, returning an instance of the Class object
getName()Returns the entity (class, interface, array class, primitive type, etc.) represented by this Class
Class[] getInterfaces()Get the interface of the current Class object
ClassLoader getClassLoader()Returns the class loader for this class
Class getSuperclass()Returns the Class representing the superclass of the entity represented by this Class
Constructor[] getConstructors()Returns an array containing some Constructor objects
Field[] getDeclaredFields()Returns an array of Field objects
Method getMethod(String name,class...paramTypes)Returns a Method object whose parameter type is paramType

Get the Class class object

  • 1. Prerequisite: The full class name of a class name is known, and the class is in the class path, which can be obtained through the static method forName() of the Class class. Class c1 = Class.forName("java.lang.Cat")

    Application scenario: It is mostly used for configuration files, reading the full path of the class, and loading the class.

  • 2. Premise: If the specific class is known, it can be obtained through the class of the class. This method is the most secure and reliable, and the program performance is the highest. Class c2 = Cat.class;

    Application scenario: It is mostly used for parameter passing, such as obtaining the corresponding constructor object through reflection.

  • 3. Premise: Know an instance of a class, call the getClass () method of the instance to get the Class object. Class c3 = object.getClass("full class name of the class");

    Application scenario: Obtain the Class object through the created object

  • 4. Other ways

    • ClassLoder cl = object.getClass().getClassLoder();
    • Class c4 = cl.loadClass("full class name of the class");
  • 5. Basic data (int, char,boolean,float,double,byte,long,short) get the Class object as follows

    Class cls = basic data type.class

  • 6. The wrapper class corresponding to the basic data type can get the Class class object through .TYPE

    Class cls = wrapper class.TYPE

Types with Class objects

  • outer class, member inner class, static inner class, local inner class, anonymous inner class
  • interface: interface
  • data
  • enum: enumeration
  • annotation: annotation
  • basic data type
  • void

class loading

Basic Instructions

The reflection mechanism is the key to the realization of dynamic language in java, that is, to realize dynamic class loading through reflection.

  • Static loading: load related classes at compile time, if not, an error will be reported, the dependency is too strong
  • Dynamic loading: Load the required class at runtime. If the class is not used at runtime, even if the class does not exist, it will not be the throne, reducing dependencies.

class loading timing

  • When the object is created (new) // statically loaded
  • When the child class is loaded, the parent class is also loaded // statically loaded
  • When calling a static member in a class //statically loaded
  • Via reflection // dynamically load Class.forName("com.test.Cat");

Class loading process diagram

Obtain class structure information through reflection

The first group: java.lang.Class class

  • getName: Get the full class name
  • getSimpleName: Get the simple class name
  • getFields: Get all public modified properties, including this class and the parent class
  • getDeclaredFields: Get all properties in this class
  • getMethods: Get all public modified methods, including this class and the parent class
  • getDeclaredMethods: Get all methods in this class
  • getConstructors: Get all the public decorated constructors of this class
  • getDeclaredConstructors: Get all constructors in this class
  • getPackage: returns package information in the form of Package
  • getSuperClass: Returns the parent class information in the form of Class. getInterfaces: Returns the interface information in the form of Class[
  • getAnnotations: Returns annotation information in the form of Annotation[]

The second group: java.lang.reflet.Field class

  • getModifiers: returns modifiers as an int

​ [Description: The default modifier is 0, public is 1, private is 2, protected is 4,static is 8,final is 16], public(1) + static (8)= 9

  • getType: returns the type in the form of Class
  • getName: returns the property name

The third group: java.lang.reflect.Method class

  • getModifiers: Return modifiers in the form of int [Description: The default modifier is 0, public is 1, private is 2, protected is 4,static is 8, final is 16]
  • getReturnType: Get the return type in the form of Class getName: Return the method name
  • getParameterTypes: Returns an array of parameter types in Class[

Group 4: java.lang.reflect.Constructor class

  • getModifiers: returns modifiers in int form getName: returns the constructor name (full class name)
  • getParameterTypes: Returns an array of parameter types as Class[]

Create objects with reflection

  • Method 1: Call the public-decorated no-argument constructor in the class
  • Method 2: Call the specified constructor in the class
  • Class related methods
    • newInstance: call the parameterless constructor in the class to get the object of the corresponding class
    • getConstructor(Class...clazz) Get all the corresponding constructor objects according to the parameter list
  • Constructor class related methods
    • setAccessible: brute force
    • newInstance(Object...object): Call the constructor.

Case demonstration

Test 1: Create an object of a certain class through reflection, requiring that there must be a public no-argument structure in the class

Test 2: Create an object of a certain class by calling a specific constructor

/*
* Demonstrates instance creation through reflection
        */
public class ReflecCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException,
            IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//1. First get the Class object of the User class
        Class<?> userClass = Class.forName("com.day02.User");
//2. Create an instance through a public no-argument constructor
        Object o = userClass.newInstance();
        System.out.println(o);
//3. Create an instance through the public parameterized constructor
/*
constructor object is
public User(String name) {//public parameterized constructor of
this.name = name;
}
*/
//3.1 Get the corresponding constructor first
        Constructor<?> constructor = userClass.getConstructor(String.class);
//3.2 Create an instance and pass in actual parameters
        Object hsp = constructor.newInstance("hsp");
        System.out.println("hsp=" + hsp);
//4. Create an instance through a non-public parameterized constructor
//4.1 Get the private constructor object
        Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
//4.2 Create an instance
//Brute-force [brute force], you can use reflection to access private constructors/methods/properties, in front of reflection, there are paper tigers
        constructor1.setAccessible(true);
        Object user2 = constructor1.newInstance(100, "Zhang Sanfeng");
        System.out.println("user2=" + user2);
    }
}
class User { //User class
    private int age = 10;
    private String name = "jack";
    public User() {//no parameter public
    }
    public User(String name) {//public parameterized constructor
        this.name = name;
    }
    private User(int age, String name) {//private parameterized constructor
        this.age = age;
        this.name = name;
    }
    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }
}

Accessing members of a class through reflection

access property

  • Get Field object based on property name

    Field f = clazz object.getDeclaredField( attribute name);

  • Breakthrough: f.setAccessible(true);//f is Field

  • Access f.set(o, value) syso(f.get(o)); //o represents the object

    Note: If it is a static property, the parameter o in set and get can be written as null

public class ReflecAccessProperty {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException,
            InstantiationException, NoSuchFieldException {
//1. Get the Class object corresponding to the Student class
        Class<?> stuClass = Class.forName("com.day02.Student");
//2. Create the object
        Object o = stuClass.newInstance();//o The run type is Student
        System.out.println(o.getClass());//Student
//3. Use reflection to get the age attribute object
        Field age = stuClass.getField("age");
        age.set(o, 88);//Manipulating properties through reflection
        System.out.println(o);//
        System.out.println(age.get(o));//Returns the value of the age property
//4. Manipulate the name property using reflection
        Field name = stuClass.getDeclaredField("name");
//Brute force on the name, you can operate the private property
        name.setAccessible(true);
//name.set(o, "jack");
        name.set(null, "jack~");//Because name is a static property, o can also be written as null
        System.out.println(o);
        System.out.println(name.get(o)); //get attribute value
        System.out.println(name.get(null));//Get property value, requires name to be static
    }
}
class Student {//kind
    public int age;
    private static String name;
    public Student() {//Constructor
    }
    public String toString() {
        return "Student [age=" + age + ", name=" + name + "]";
    }
}

access method

  • Get the Method method object based on the method name and parameter list: Method m =
    clazz.getDeclaredMethod( method name, XX.class);//Get all methods of this class

  • Get the object: Object o=clazz.newlnstance();

  • Blast: m.setAccessible(true);

  • Access: Object returnValue = m.invoke(o, actual parameter list);//o is the object

    Note: If it is a static method, the parameter o of invoke can be written as null!

/* Demonstrates calling a method via reflection
        */
public class ReflecAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException,
            InstantiationException, InvocationTargetException, NoSuchMethodException {
//1. Get the Class object corresponding to the Boss class
        Class<?> bossCls = Class.forName("com.day02.Boss");
//2. Create the object
        Object o = bossCls.newInstance();
//3. Call the public hi method
//Method hi = bossCls.getMethod("hi", String.class);//OK
//3.1 Get the hi method object
        Method hi = bossCls.getDeclaredMethod("hi", String.class);//OK
//3.2 Call
        hi.invoke(o, "jack~");
//4. Invoke a private static method
//4.1 Get the say method object
        Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
//4.2 Because the say method is private, it needs to be broken. The principle is the same as the constructor and property mentioned above
        say.setAccessible(true);
        System.out.println(say.invoke(o, 100, "Zhang San", 'male'));
//4.3 Because the say method is static, it can also be called like this, and null can be passed in
        System.out.println(say.invoke(null, 200, "Li Si", 'Female'));
//5. In reflection, if the method has a return value, it returns Object uniformly, but its operation type is the same as the return type defined by the method
        Object reVal = say.invoke(null, 300, "Wang Wu", 'male');
        System.out.println("reVal type of run=" + reVal.getClass());//String
//Demonstrating a returned case
        Method m1 = bossCls.getDeclaredMethod("m1");
        Object reVal2 = m1.invoke(o);
        System.out.println("reVal2 type of run=" + reVal2.getClass());//Monster
    }
}
class Monster {}
class Boss {//kind
    public int age;
    private static String name;
    public Boss() {//Constructor
    }
    public Monster m1() {
        return new Monster();
    }
    private static String say(int n, String s, char c) {//static method
        return n + " " + s + " " + c;
    }
    public void hi(String s) {//normal public method
        System.out.println("hi " + s);
    }
}
println("reVal2 type of run=" + reVal2.getClass());//Monster
    }
}
class Monster {}
class Boss {//kind
    public int age;
    private static String name;
    public Boss() {//Constructor
    }
    public Monster m1() {
        return new Monster();
    }
    private static String say(int n, String s, char c) {//static method
        return n + " " + s + " " + c;
    }
    public void hi(String s) {//normal public method
        System.out.println("hi " + s);
    }
}

Tags: Java

Posted by Doug G on Thu, 15 Sep 2022 02:21:00 +0930