Reflection mechanism in java

Posted by belaraka on Sun, 24 Oct 2021 08:15:43 +0200

one   The concept of reflection

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 variables and methods of any class member, and call the properties and methods of any object. This dynamically obtained program information and the function of dynamically calling objects are called the reflection mechanism of Java language. Reflection is regarded as the keyword of dynamic language.

two   Class loader

Java Classloader is a part of Java Runtime Environment, which is responsible for dynamically loading java classes into the memory space of java virtual machine. java has three kinds of loaders by default: bootstrap classloader, ExtensionClassLoader and App ClassLoader. Bootstrap classloader: a loader embedded in the JVM kernel. The loader is written in C + + language and mainly loads java_ The class library under home / lib, boot class loader, cannot be directly used by applications.

ExtensionClassLoader: ExtensionClassLoader is written in JAVA, and its parent class loader is Bootstrap. It is implemented by sun.misc.Launcher$ExtClassLoader and mainly loads JAVA_ Class libraries in the home / lib / ext directory. Its parent loader is bootstrappclassloader app classloader

(application class loader): App ClassLoader is an application class loader, which is responsible for loading all jar s and class files in the application classpath directory. Its parent loader is Ext ClassLoader

  Parents Delegation Model

Parent delegation model: if a class loader receives a class loading request, it will not try to load the class itself, but transfer the request to the parent class loader to complete. This is true for class loaders at every level. Therefore, all class loading requests should be passed to the top-level startup class loader. Only when the parent class loader feeds back that it cannot complete the loading request (this class is not found in its search scope), the child class loader will try to load it by itself. The benefit of delegation is to avoid some classes being loaded repeatedly.

Load path problem

The file under src path is loaded by default, but when the resource root directory exists in the project, the file under resource root will be loaded.

 @Test
    public void Test() throws IOException {
        InputStream is = Class name.class.getClassLoader().getResourceAsStream("File name");
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String s = br.readLine();
        System.out.println(s);
        br.close();

    }

Class object

To understand a Class, you must first obtain the bytecode file object of the Class. In Java, after each bytecode file is loaded into memory, there is a corresponding Class object.

three    Several ways to get Class

1. If you know the class name when writing code and the class already exists, you can get the class object of a class through package name. Class name. Class

2. If you have an object of a Class, you can get the Class object of a Class through Class object. getClass()

3. If you know the name of the class when writing the code, you can use it through Class.forName("package name + class name"). It can also be used when the class does not exist (the code will not be red, and errors will be reported when running alone, which is more suitable for dynamic programming). If the specified class is not found, ClassNotFoundException will be reported

Get the class object of a class in the above three ways. When calling, if the class does not exist in memory, it will be loaded into memory! If the class already exists in memory, it will not be loaded repeatedly, but reused!

four    Constructor create object

Common methods: newInstance(Object... para)

Call this construction method to create the corresponding Object parameter: it is an Object type variable parameter, and the passed parameter order must match the order of the formal parameter list in the construction method!

setAccessible(boolean flag)

If the flag is true, it means that the access permission check is ignored! (method that can access any permission)

Get the construction method of a class through the class object

1. Obtain the specified single constructor getconstructor (class object array of parameter type) through the specified parameter type

For example, the construction method is as follows: Person(String name,int age)

The code of this construction method is as follows:

Constructor c = p.getClass().getConstructor(String.class,int.class);

2. Get the constructor array getConstructors();

3. Get a single constructor getdeclaraedconstructor (class object array of parameter type) of all permissions

4. Get the constructor array getdeclaraedconstructors() of all permissions;

Example:

package bean;

public class Person {
    private int age;
    private String name;
    public String phoneNumber;

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                '}';
    }

    //Private construction method
   private Person(String name) {
       this.age = 18;
       this.name = name;
    }


    public Person() {
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package test;
import bean.Person;
import java.lang.reflect.Constructor;

public class Test {
    public static void main(String[] args) throws Exception {
        Class<Person> aClass = (Class<Person>) Class.forName("bean.Person");
        //No parameter constructor found
        Constructor<Person> c = aClass.getConstructor();
        //Use the parameterless construction method to create objects
        Person p = c.newInstance();
        System.out.println(p);

        //Find the constructor containing String name and int age
        Constructor<Person> c1 = aClass.getConstructor(int.class,String.class);
        //Use the full parameter construction method to create objects
        Person p1 = c1.newInstance( 18,"Li Wei");
        System.out.println(p1);

        //Constructor for obtaining all permissions
        Constructor<Person> d = aClass.getDeclaredConstructor(String.class);
        //Ignore permission check
        d.setAccessible(true);
        Person p2 = d.newInstance("Liu Yang");
        System.out.println(p2);
        System.out.println("getDeclaredConstructors Method can obtain all permissions");
        Constructor<?>[] gdc = aClass.getDeclaredConstructors();
        for (Constructor<?> gd : gdc) {
            System.out.println(gd);
        }
        System.out.println("getConstructors Method can only get public Method modified constructor");
        Constructor<?>[] gdc1 = aClass.getConstructors();
        for (Constructor<?> gd : gdc1) {
            System.out.println(gd);
        }

    }
}

Output results:

  5 .     Get Method

Get the method of a class through the class object

1. getMethod(String methodName , class.. clss)

Get a method (public decorated) according to the type and method name of the parameter list

2. getMethods();

Get all the methods of a class (public modified)

3. getDeclaredMethod(String methodName , class.. clss)

Get a method according to the type and method name of the parameter list (all except inheritance: private, common, protected, default)

4. getDeclaredMethods();

Get all methods of a class (all except inheritance: private, common, protected, default)

Method execution method

 invoke(Object o,Object... para) :

Call method,

Parameter 1. Object parameter of the method to be called

2. List of parameters to be passed

Example:

Use the person class above

//Load class
        Class<Person> aClass = (Class<Person>) Class.forName("bean.Person");
        //Gets the constructor in the class
        Constructor<Person> c = aClass.getConstructor();
        //create object
        Person person = c.newInstance();
        //Gets the method of the class
        Method setName = aClass.getMethod("setName", String.class);
        //Method for obtaining all permissions
        Method setAge = aClass.getDeclaredMethod("setAge", int.class);
        //Ignore access check
        setAge.setAccessible(true);
        //Parameter 1. Which object needs to execute setName method
        //Parameter 2. Generation 0-n passed when calling the method
        setName.invoke(person, "Zhang San");
        setAge.invoke(person, 18);
        System.out.println(person);

six    Get Field    Get the properties of a class through the class object

1. getDeclaredField(String filedName)   Get a property object (all properties) according to the name of the property

2. getDeclaredFields()                             Get all properties

3. getField(String filedName)                 Get a property object (public property) according to the name of the property

4. getFields()                                           Get all properties (public)

Object type of Field property

Common methods:

1. get(Object o )               Parameter: the object to get the property gets the property value of the specified object

2. set(Object o , Object value)

Parameter 1. Object to set attribute value

Parameter 2. The value to be set sets the value of the property of the specified object

3. getName()                   Gets the name of the property

4. setAccessible(boolean flag)

If the flag is true, it means that the access permission check is ignored! (properties that can access any permission)

     //Load class
        Class c = Class.forName("bean.Person");
        Constructor ct = c.getConstructor();
        
        Object o = ct.newInstance();
        Field phoneNumber = c.getField("phoneNumber");
        phoneNumber.set(o, "13843838438");


        Field name = c.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o, "Zhang San");
        System.out.println(o);

seven   Using reflection to obtain annotation information (implementation principle of ORM framework)

Get all annotation objects of class / property / method

Annotation[] as = Class/Field/Method.getAnnotations();
for (Annotation a : as) {
System.out.println(a);
}

  Get annotation object of class / property / method according to type

Annotation type object name = (annotation type) c.getannotation (annotation type. class);

Example:

Package structure

package demo;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.TYPE})
@Documented
public @interface ColumnAnnotation {
    /**
     * Description column name
     * @return
     */
    String columnName();

    /**
     * Description type
     * @return
     */
    String type();

    /**
     * Describes the length of the data
     * @return
     */
    String length();
}
package demo;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface TableAnnotation {
    /**
     * Name used to describe the table
     * @return
     */
    String value();
}
package demo;
import java.util.Objects;
//@ColumnAnnotation(columnName = "aa",type = "aa",length = "aa")
@TableAnnotation("test_book")
public class Book {
    @ColumnAnnotation(columnName = "id",type = "int",length = "11")
    private int id;
    @ColumnAnnotation(columnName = "name",type = "varchar",length = "20")
    private String name;
    @ColumnAnnotation(columnName = "info",type = "varchar",length = "500")
    private String info;

    public Book() {
    }

    public Book(int id, String name, String info) {
        this.id = id;
        this.name = name;
        this.info = info;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return id == book.id &&
                Objects.equals(name, book.name) &&
                Objects.equals(info, book.info);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, info);
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}
package demo;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class Demo {
    public static void main(String[] args) throws Exception {
        Class c = Class.forName("demo.Book");
        //Get all the annotations above the book class and get a set of annotations
        Annotation[] as = c.getAnnotations();
        for (Annotation a : as) {
            System.out.println(a);
        }
        //Get value by annotation name
        TableAnnotation annotation = (TableAnnotation) c.getAnnotation(TableAnnotation.class);
        //The name of the annotation
        System.out.println(annotation);
        //Gets the value of the annotation
        String value = annotation.value();
        System.out.println(value);
        //Get all properties
        Field[] fs = c.getDeclaredFields();
        for (Field f : fs) {
            ColumnAnnotation ca = f.getAnnotation(ColumnAnnotation.class);
            System.out.println(f.getName()+"Property, corresponding to the field of the database"+ca.columnName()+",data type"+ca.type()+",Length of data"+ca.length());


        }

    }
}

Operation results:

 

Topics: Java reflection