Java learning 18: Reflection

Keywords: Java Back-end

18. Reflection

Reflection mechanism

Reflection mechanism allows the program to obtain the internal information of any class (such as member variables, constructors, member methods, etc.) with the help of Reflection API during execution, and can operate the properties and methods of objects.

After loading the Class, a Class object is generated in the queue (a Class has only one Class object), which contains the complete structure information of Lei Class. Get the structure of the Class through this object.

Illustration of reflection principle of class

Reflex mechanism

  1. Determine the class to which an object belongs at run time
  2. Construct any object at run time
  3. Get the member variables and methods of any object at run time
  4. Call the member variables and methods of any object at run time
  5. 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 a class, and the Method object represents the Method of a class
  3. Java.lang.reflect.feed: represents the member variable of a class, and the Field object represents the member variable of a class
  4. java.lang.reflect.Constructor: represents the construction method of the class, and the Constructor object represents the Constructor

example:

//(1) Load the Class and return the object cls of Class type 

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 operation=" + o.getClass()); //Operation type 

//(3) Get the method object of methodName"hi" of class com.hspedu.Cat you loaded through cls 

// That is, in reflection, methods can be regarded 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)

//java.lang.reflect.Field: represents the member variable of a class, and the Field object represents the member variable of a class 
//Get name field 
//getField cannot get private properties 
Field nameField = cls.getField("age"); // 

System.out.println(nameField.get(o)); // Legacy object. Member variable, reflection: member variable object. Get (object) 

//java.lang.reflect.Constructor: represents the construction method of the class, and the Constructor object represents the Constructor 

Constructor constructor = cls.getConstructor(); //() can specify the constructor parameter type and return a parameterless constructor 

System.out.println(constructor);//Cat() 

Advantages and disadvantages of reflection

  1. Advantages: you can dynamically create and use objects, use them flexibly, and the bottom core of the framework
  2. Disadvantages: reflection is basically used to explain execution, which has an impact on execution speed

Reflection call Optimization: - turn off access checking

Method, Field and Constructor objects all have setAccessible() method. This method is used to turn on and off the access security check. The parameter value is set to true, which means that the access check of the reflected object is cancelled when it is used to improve the efficiency of reflection.

Class class

Class object -- > that is, an object of type class. Loading a class into memory will create a corresponding class object

  1. Class is also a class, so it also inherits the Object class
  2. Class objects are not new, but created by the system
  3. For the Class object of each Class, there is only one copy in memory, because the Class is loaded only once
  4. Each Class instance will remember which Class instance it was generated from
  5. Through the Class object, you can get the complete structure of a Class through a series of API s
  6. Class objects are stored in the heap
  7. The bytecode binary data of a class is placed in the method area. In some places, it is called class metadata (including variable name, method name, access permission, etc.)

Object with Class

  1. External class, internal class
  2. Interface
  3. array
  4. enumeration
  5. annotation
  6. Basic data type
  7. void

Class common methods:

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-J6rX0Vjs-1636426526967)(E:\java\note\image.png)]

String str = "com.Cat";
//Get Class object,? Represents an ambiguous java type
Class<?> class1 = Class.forName(str);
System.out.println(class1);//Displays which class the class1 object is
System.out.println(class1.getClass());//Operation type
System.out.println(class1.getPackage().getName());//Get package name
System.out.println(class1.getName());
Object obj = class1.newInstance();//Create objects by reflection
Field field = class1.getField("name");//Get properties through reflection
field.set(obj,"floret");//Assignment by field object
Object obj2 = field.get(obj);//Get value
System.out.println(obj2);//output

Get Class object

  1. Class.forName() get: used for configuration files, reading the full path, and loading classes
// 1. Class.forName
Class<?> carClass1 = Class.forName("com.lsgstudy.Car");
System.out.println(carClass1); // class com.lsgstudy.Car
  1. class name. class acquisition: it is mostly used for parameter passing, and the corresponding constructor object is obtained through reflection
// 2. Class name.class
Class<Car> carClass2 = Car.class;
System.out.println(carClass2); // class com.lsgstudy.Car
  1. Get object name. getClass
// 3. Object name. getClass
Car car = new Car();
Class<? extends Car> carClass3 = car.getClass();
System.out.println(carClass3); // class com.lsgstudy.Car
  1. Get through class loader
// 4. Get the Class object of the Class through the Class loader
// Get class loader
ClassLoader classLoader = car.getClass().getClassLoader();
// Get the Class object through the Class loader
Class<?> carClass4 = classLoader.loadClass("com.lsgstudy.Car");
System.out.println(carClass4); // class com.lsgstudy.Car
  1. Get Class object of basic data type
// 5. Get Class object of basic data type
Class<Integer> integerClass = int.class;
System.out.println(integerClass); // int
  1. The basic data type wrapper Class gets the Class object
// 6. Get the Class object of the wrapper Class
Class<Integer> type = Integer.TYPE;
System.out.println(type); // int
  1. Others: package, parent class, interface, annotation
Class<?> personCls = Class.forName("com.lsgstudy.reflection.class_.Person");

// Get the package information of the Class corresponding to the Class object
System.out.println("=========obtain Class Package information of the class corresponding to the object=========");
Package personPackage = personCls.getPackage();
System.out.println(personPackage.getName());
// Gets the Class object of the parent Class of the Class corresponding to the Class object
System.out.println("=======obtain Class The name of the parent class of the class corresponding to the object Class object===========");
Class<?> superclass = personCls.getSuperclass();
System.out.println(superclass.getName());

// Gets the Class object of the interface of the Class corresponding to the Class object
System.out.println("========obtain Class Object corresponds to the interface of the class Class object==========");
Class<?>[] interfaces = personCls.getInterfaces();
for (Class<?> anInterface : interfaces) {
   System.out.println(anInterface.getName());
}

// Gets the annotation of the Class corresponding to the Class object
System.out.println("===========obtain Class The annotation of the class corresponding to the object Class object============");
Annotation[] annotations = personCls.getAnnotations();
for (Annotation annotation : annotations) {
   System.out.println(annotation);
}

Note: in fact, the Class object obtained by int and Integer is the same, because it will be automatically boxed and unpacked at runtime

Class loading

  1. Static loading: load relevant classes during compilation. If there is no error, it is too dependent
  2. Dynamic loading: relevant classes are loaded at runtime. If this class is not used at runtime, no error will be reported, which reduces the dependency

Class loading time:

  1. When creating an object (new)
  2. When subclasses are loaded
  3. When calling a static member of a class
  4. Dynamic loading through reflection

Class loading process

The following picture shows the process of Java program from source code to running

Source code to run

Detailed process of class loading

Loading: the main purpose of the JVM at this stage is to convert bytecode from different data sources (possibly class files, jar packages, or even networks) into binary byte streams, load them into memory, and generate a java.lang.Class object representing this class

Connection: divided into three stages

  1. Verification: the purpose is to ensure that the information contained in the byte stream of the Class file meets the requirements of the current virtual machine and will not endanger the security of the virtual machine itself. Including file format verification (whether it starts with magic number oxcafebebe), metadata verification, bytecode verification and symbol reference verification. Consider using the - Xverify:none parameter to turn off most of the Class verification measures and shorten the loading time of virtual machine classes
  2. Preparation: the JVM will allocate memory and initialize static variables at this stage (corresponding to the default initial values of data types, such as 0, 0L, null, false, etc.). The memory used by these variables will be allocated in the method
class A {
   // Different types of attribute processing methods in the preparation stage
   // n1 is an instance attribute, not a static variable, so memory will not be allocated during the preparation phase
   // n2 is a static variable, and n2 is the default initialization 0 instead of 20
   // n3 is static and final is a constant, which is different from static variables, because once assigned, n3 = 30 remains unchanged
   public int n1 = 10;
   public static int n2 = 20;
   public static final int n3 = 30;
}
  1. Resolution: the process by which the virtual machine replaces the symbolic reference in the constant pool with a direct reference

Initialization: the Java program code defined in the class will not be executed until the initialization stage. This stage is the process of executing the () method.

() method is that the compiler automatically collects the assignment actions of all static variables in the class and the statements in the static code block according to the order in which the statements appear in the source file, and combines them.

Virtual opportunity ensures that the () method of a class is locked and synchronized correctly in a multithreaded environment. If multiple threads initialize a class at the same time, only one thread will execute the () method of this class, and other threads need to block and wait until the active thread finishes executing the () method

[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-2LYli6UE-1636426526974)(E:\java\note\image.png)]

Get class structure information through reflection

  1. getName: get the full class name
  2. getSimpleName: get the simple class name
  3. getFields: get the properties of all public modifiers, including the properties of this class and its parent class
  4. Getdeclaraedfields: get all the attributes in this class
  5. getMethods: get all public modified methods, including this class and its parent class
  6. Getdeclaraedmethods: get all the methods of this class
  7. getConstructors: get constructors of all public modifiers, including this class
  8. Getdeclaraedconstructors: get all constructors in this class
  9. getPackage: returns Package information in the form of Package
  10. getSuperClass: returns parent Class information in the form of Class
  11. getInterfaces: returns interface information in the form of Class []
  12. getAnnotations: returns annotation information in the form of Annotations []

Attribute: Field

Get property object

  1. Get the public property (including the of the parent class)
Field name = personClass.getField("name");
  1. Get all properties (excluding those of the parent class)
Field age = personClass.getDeclaredField("age");

common method

  1. set: modify attributes
// Set (object name, modified content)
name.set(o,"Li Hua");
  1. Get: get the value of the property
// Get (object name)
// The return value is the Object type, and the run type is the actual type, which can be transformed downward
Object personName = name.get(o);
  1. getModifiers: get modifier value
// Note: the default modifier is 0, public is 1, private is 2, protected is 4, static is 8, and final is 16
// public(1) + static(8) = 9
int modifiers = name.getModifiers();
  1. getType: gets the Class object of the data type
Class<?> type = name.getType();
  1. getName: get property name
String fieldName = name.getName();

be careful:

  1. If the property is non-public, the access check needs to be turned off for assignment and value acquisition operations
  2. If the property is static, the method that needs to pass in the object name can pass in null

Code example

public static void main(String[] args) throws Exception {
    // Gets the Class object of the Person Class
    Class<?> personClass = Class.forName("com.lsgstudy.reflection.Person");
    // Create instance
    Object o = personClass.newInstance();

    // public property
    // Get property object
    Field name = personClass.getField("name");
    // set a property
    name.set(o,"Li Hua");
    System.out.println(o);

    String a = "hhh";
    // private static property
    // Get property object
    // Because it is a private property, getDeclaredField is used
    Field age = personClass.getDeclaredField("age");
    // Private property. If you want to assign a value, you need to close the access check first
    age.setAccessible(true);
    // static type, you do not need to pass in the object of this class
    age.set(a,5);
    System.out.println(age.get(null));
}

Method: method

Get method object

  1. Get the public method (including the of the parent class)
// Getmethod (method name, Class object of parameter data type)
Method m1 = dogClass.getMethod("m1", int.class);
  1. Get all methods (excluding those of the parent class)
// Getdeclaraedmethod (method name, Class object of parameter data type)
Method m2 = dogClass.getDeclaredMethod("m2", String.class);

common method

  1. invoke: Execute method
// Invoke (object name, method parameter (variable parameter))
// If the method has a return value, the return value is uniformly Object, which can be transformed downward
Object invoke = m1.invoke(o, 5);
  1. getName: get method name
String name = m1.getName();
  1. getModifiers: get modifier value
// Note: the default modifier is 0, public is 1, private is 2, protected is 4, static is 8, and final is 16
// public(1) + static(8) = 9
int modifiers = m1.getModifiers();
  1. getParameterTypes: gets the Class object of the parameter data type
Class<?>[] parameterTypes = m1.getParameterTypes();
  1. getReturnType: gets the Class object of the return type
Class<?> returnType = m1.getReturnType();

be careful:

  1. If the method is not public, you need to close the access check before calling the method operation
  2. If the method is static, the method that needs to pass in the object name can pass in null

Code example

public static void main(String[] args) throws Exception{
    // Gets the Class object of the Dog Class
    Class<?> dogClass = Class.forName("com.lsgstudy.reflection.Dog");
    // Create instance
    Object o = dogClass.newInstance();

    // public method
    // Get method object
    Method m1 = dogClass.getMethod("m1", int.class);
    // Dropping method
    // Method has a return value. The return value is Object
    Object invoke = m1.invoke(o, 5);
    System.out.println(invoke);


    // private static method
    // Get the method object. The private method must be obtained with getDeclaredMethod
    Method m2 = dogClass.getDeclaredMethod("m2", String.class);
    // Calling the private method requires that the access check be turned off
    m2.setAccessible(true);
    // The static method does not require an object of this class
    Object[] arr = (Object[])m2.invoke(null, "Li Hua");
    System.out.println(arr[1]);
}

Constructor: constructor

Get method object

  1. Get public constructor
// Getconstructor (parameter type Class object list)
Constructor<?> constructor = userClass.getConstructor(int.class);
  1. Get all constructors
// Getdeclaraedconstructor (parameter type Class object list)
Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class, int.class);

common method

  1. newInstance: create an instance
// Newinstance (method parameter (variable parameter))
// The return value is an Object and can be transformed downward
Object user2 = constructor.newInstance(15);
  1. getName: get constructor name (full class name)
String name = constructor.getName();
  1. getModifiers: get modifier value
// Note: the default modifier is 0, public is 1, private is 2, protected is 4, static is 8, and final is 16
// public(1) + static(8) = 9
int modifiers = constructor.getModifiers();
  1. getParameterTypes: gets the Class object of the parameter data type
Class<?>[] parameterTypes = constructor.getParameterTypes();

Note: if a non-public constructor directly creates an instance, it will throw an exception and need to close the access check

Code example

Three methods of creating instances

public static void main(String[] args) throws Exception{
    // Gets the Class object of the User Class
    Class<?> userClass = Class.forName("com.lsgstudy.reflection.User");

    // 1. Create an instance with a parameterless constructor
    Object user1 = userClass.newInstance();
    System.out.println(user1);

    // 2. Create an instance with the public parameterized constructor
    // Get the constructor before creating the instance
    Constructor<?> constructor = userClass.getConstructor(int.class);
    Object user2 = constructor.newInstance(15);
    System.out.println(user2);

    // 3. Create an instance with a non public parameterized constructor
    // Get the constructor. Because it is not public, you need to use getDeclaredConstructor
    Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class, int.class);
    // If a non-public constructor directly creates an instance, it will throw an exception and need to close the access check
    declaredConstructor.setAccessible(true);
    Object user3 = declaredConstructor.newInstance("Zhang Sanfeng", 30);
    System.out.println(user3);
}

Posted by Kurtismonger on Wed, 10 Nov 2021 04:34:38 -0800