[java notes] reflection mechanism

Overview:

Dynamic language:

A class of languages ​​whose structure can be changed at runtime. For example, new functions, objects, and code can be introduced; existing functions can be deleted or other structural changes.

Static language:

A language whose runtime structure is immutable is a static language.

Java is not a dynamic language, but it can be said to be a quasi-dynamic language, that is, java has a certain dynamic nature, and the reflection mechanism can be used to obtain characteristics similar to dynamic languages.


Reflection mechanism: Java Reflection. Allows the program to obtain the internal information of any class by means of the Reflection API during execution, and can directly manipulate the internal property methods of any object

After the class is loaded, an object of type Class is generated in the method area of ​​the heap memory (a class has only one Class object), and this object contains the complete structural information of the class. We can see the structure of the class through this object. This object is like a mirror, through which the structure of the class can be seen, so the image is called reflection.

Reflection advantages:

Can achieve dynamic object creation and compilation, flexible

Reflection Disadvantages:

Affects performance.


Reflection related API:

java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Construtor:代表类的构造器

 

 

  A class has only one class object in memory

After a class is loaded, the entire structure of the class is encapsulated in the Class object

 Class class:

The Class getclass() method is defined in the Object class, and this method will be inherited by all subclasses

For each class, JRE reserves an invariant Class type object for it, and a class type object contains a specific structure

●Class itself is also a class

●Class objects can only be created by the system

● A load will only have one instance of Class in the JVM

A Class object corresponds to a .class file loaded into the JVM

Each instance of a class will remember which Class instance it was generated from

●Through Class, all loaded structures of a class can be completely obtained

The Class class is the root of Reflection. For any class you want to dynamically load and run, you must first obtain the corresponding Class object

Get an instance of the Class class:

If the specific class is known, it can be obtained through the class attribute of the class, which has high security and reliability.

Class c=Person.class;

If an instance of a class is known, call the getClass() method of the instance to obtain the Class object

Class c=person.getClass();

The full class name of a class is known, and the class is in the classpath, which can be obtained through the static method forName() of the Class class, which may throw a ClassNotFoundException

Class c=Class.forName("路径/类名")

 

        Person person=new Student();
        //通过对象获得
        Class c1=person.getClass();
        //通过forname获得
        Class c2=Class.forName("Reflection.Student");
        //通过类名.class获得
        Class c3=Student.class;
   ------------------------------------------------------

        //基本内置类型的包装类都有一个TYPE属性
        Class c4=Integer.TYPE;
        System.out.println(c4.hashCode());
        //获得父类类型Person
        Class c5=c1.getSuperclass();

What types can have Class objects?

class: outer class, member inner class, static inner class, local inner class, anonymous inner class

interface: interface

[]: array

enum: enumeration 

annotation: annotation

primitive type: basic data type

void

As long as the element type is the same as the dimension, it is a class 

JAVA memory analysis:

The loading of classes and the understanding of ClassLoader:

load:

Load the bytecode content of the class file into memory and convert these static data into runtime data structures in the method area

Then generate a java.lang.Class object representing this class

Link:

The process of incorporating the binary code of a Java class into the running state of the JVM

Validation: Make sure the loaded classes conform to the JVM specification and have no security concerns

Preparation: The stage of formally allocating memory for class traversal (static) and setting the default initial value of class variables, which will be allocated in the method area

Resolution: The process of replacing the symbolic reference (constant name) of the virtual machine constant pool with a direct reference (address)

initialization:

The process of executing the class constructor <clinit>() method. The class constructor <clinit>() method is generated by automatically collecting assignments of all class variables in the class at compile time and combining the statements in the static code block. (The class constructor is for constructing class information, not the constructor for constructing objects of this class)

When initializing a class, if you find that its parent class has not been initialized, you need to trigger the initialization of its parent class first

The virtual machine ensures that a class <clinit>() method is properly locked and synchronized in a multithreaded environment.

   Active reference of a class (class initialization must occur)
➢ When the virtual machine starts, initialize the class where the main method is located ➢
New object of a class
➢ Call static members (except final constants) and static methods of the class
➢ Use java.lang The method of the .reflect package makes a reflection call to the class
➢ When a class is initialized, if its parent class has not been initialized,
   the passive reference of its parent class will be initialized first (class initialization will not occur)
➢ When accessing a static domain , only the class that actually declares the field will be initialized. For example: when a static variable of a parent class is referenced through a subclass, it will not cause the initialization of the subclass.
➢ Defining a class reference through an array will not trigger such initialization.
➢ Reference constants will not trigger such initialization (constants are stored in the linking phase. into the constant pool of the calling class)

class loader:

➢The role of class loading: load the bytecode content of the class file into memory, convert these static data into the runtime
data structure of the method area, and then generate a java.lang.Class object representing this class in the heap , as the access
entry for class data in the method area .
➢ Class Cache: The standard JavaSE class loader can look up classes on demand, but - once a class is loaded into the class loader, it will
remain loaded (cached) for a period of time. However, the JVM garbage collection mechanism can recycle these Class objects
 

Get class information:

        Class c1=Class.forName("Reflection.User");
        //获得类的名字
        System.out.println(c1.getName());//获得包名+类名
        System.out.println(c1.getSimpleName());//获得类名
        //获得类的属性
        Field[]field11=c1.getFields();//获取Public属性
        Field[]fields=c1.getDeclaredFields();//获取全部属性
        //获取指定属性的值
        Field name=c1.getDeclaredField("name");
        //获得类的方法
        Method[]methods=c1.getMethods();//获得本类及其父类的全部Public方法
        methods=c1.getDeclaredMethods();
        //获取类的指定方法
        //需要传入参数类型
        Method getName=c1.getMethod("getName",null);
        Method setName=c1.getMethod("setName",String.class);
        //获取构造器
        Constructor[] constructors = c1.getConstructors();
        constructors=c1.getDeclaredConstructors();
        //获取指定的构造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class,int.class,int.class);

Create objects dynamically through reflection

       //通过构造器创建对象
        Class c1=Class.forName("Reflection.User");
        //获取构造器后newInstance
        User user=(User) 
      c1.getDeclaredConstructor(String.class,int.class,int.class).newInstance("李",001,18);
        System.out.println(user);
        //通过反射调用方法:invoke
        c1.getDeclaredMethod("setName", String.class).invoke(user,"asd");
        //invoke:激活  (对象,方法的参数值)

        //通过反射操作属性

      Field name=c1.getDeclaredField("name");
      name.setAccessible(true);//设置私有成员的值时需要设置为true,否则访问不了

         name.set(user,"lll");

If the method or field is declared as private, you need to explicitly call the setAccessible(true) method before calling the method to make the private method accessible

setAccessible: switch to enable and disable access security checks

Method, Field, Constructor objects all use the setAccssible() method

The parameter value is true, indicating that the reflected object should cancel the java language access check when it is used.

*If reflection must be used in the code, and the code needs to be called frequently, set to true

* Private members that were otherwise inaccessible can also be accessed

A parameter value of false indicates that the reflected object should implement java language access checking

Performance Analysis:

 Reflection to get annotations

        Class aClass = Class.forName("Reflection.Student1");
        //通过反射获得注解
        Annotation[] annotations = aClass.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);//@Reflection.Table("db_stu")
        }
        Table table=(Table)aClass.getAnnotation(Table.class);
        System.out.println(table.value());//db_stu

        //获得类指定的注解
        Field f=aClass.getDeclaredField("name");
        FieldTable annotation = f.getAnnotation(FieldTable.class);
        System.out.println(annotation);//@Reflection.FieldTable(colName="db_name", type="varchar", length=3)
        System.out.println(annotation.colName());// db_name
        System.out.println(annotation.type());//varchar
        System.out.println(annotation.length());//3

    }
}
@Table("db_stu")
class Student1{
    @FieldTable(colName = "db_id",type = "int",length =10)
    private int id;
    @FieldTable(colName = "db_age",type="int",length = 10)
    private int age;
    @FieldTable(colName = "db_name",type="varchar",length = 3)
    private String name;

    public Student1() {
    }

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

    public int getId() {
        return id;
    }

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

    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
    String value();
}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldTable{
    String colName();
    String type();
    int length();
}

Guess you like

Origin blog.csdn.net/m0_52043808/article/details/124076887