Reflection mechanism
+JVM explains creating objects at runtime (classLoader)
Overview of java reflection mechanism
Dynamic language-------------------------------------------------------------------------
◆ it is a kind of language that can change its structure at run time: for example, new functions, objects and even code can be introduced, existing functions can be deleted or other structural changes. Generally speaking, the code can change its structure according to some conditions at run time
◆ main dynamic languages: Object-C, c#, Javascript, PHP, Python, etc.
Static language-------------------------------------------------------------------------
◆ corresponding to dynamic language, the language with immutable runtime structure is static language. Such as Java, C, C + +.
◆ Java is not a dynamic language, but Java can be called "quasi dynamic language". That is, Java has certain dynamics. We can use reflection mechanism to obtain characteristics similar to dynamic language. The dynamic nature of Java makes programming more flexible
Java Reflection -- Reflection Mechanism
◆ reflection is the key to Java being regarded as a dynamic language. The reflection mechanism allows the program to obtain the internal information of any class with the help of Reflection APLI during execution, and can directly operate the internal properties and methods of any object.
Class c=Class forname(java. lang String")
Class class is the core class of management reflection - Object also has a getClass()
◆ after loading the Class, an object of Class type is generated in the method area of heap memory (a Class has only one Cass object), which contains the complete Class structure information. We can see the structure of the Class through this object. This object is like a mirror, through which we can see the structure of the Class, so we vividly call it reflection
Normal method: import the required "package class" – > name and obtain the instantiated object through new instantiation – >
Reflection method: instantiate the object – > getClass () method – > get the complete "package class" name
Research and application of Java reflection mechanism
Functions provided by Java reflection mechanism
◆ judge the class of any object at runtime
◆ construct the object of any class at runtime
◆ judge the member variables and methods of any class at run time
◆ get generic information at runtime
◆ call the member variables and methods of any object at runtime
◆ handling annotations at runtime
◆ generate dynamic agents
advantage
It can be compiled dynamically to reflect flexibility
shortcoming
It has an impact on performance. Using reflection is basically an interpretation operation. We can tell the JVM what we want to do and it meets our requirements. Such operations are always slower than performing the same operation directly.
Main api
java. lang Class: represents a class
java lang reflect Method: represents the method of the class
java lang. reflect Field: represents the member variable of the class
java. lang reflect Constructor: represents the constructor of the class
Class class
◆ the following methods are defined in the object class, which will be inherited by all subclasses
public final Class getclasso
◆ the type of the return value of the above method is a Cass class, which is the source of Java reflection. In fact, the so-called reflection is well understood from the running results of the program,
That is, you can find the name of the class through object reflection
◆ information that can be obtained after the object looks in the mirror: the attributes, methods and constructors of a class, and which interfaces a class implements. For each class, JRE reserves an object of the same Cass type. A Cass object contains information about a specific structure (class/interface/enum/ annotation/primitive type/od).
◆ Cass itself is also a class
◆ Cass objects can only be created by the system
◆ a loaded class will only have one Cass instance in the JVM
◆ a Cass object corresponds to a class file loaded into the JVM
◆ the instance of each class will remember which Cass instance it was generated from
◆ all loaded structures in a Class can be completely obtained through Class
◆ Class is the root of Reflection. For any Class you want to dynamically load and run, you have to obtain the corresponding Class object first
Common methods of Class
Method name | Function description |
---|---|
static Classforname(String name) | Returns the Class object with the specified Class name |
Object newlnstance() | Call the default constructor to return an instance of the Class object |
getName() | Returns the name of the entity (class, interface, array class or void) represented by this Cass object |
Class getSuperClass() | Returns the CASS object of the parent class of the current Cass object |
Class[] getinterfaces() | Gets the interface of the current Class object |
ClassLoader getClassLoader() | Returns the class loader for this class |
Constructor[] getConstructors() | Returns an array containing some Constructor objects |
Method getMothed( String name, Class.T) | Returns a Method object whose formal parameter type is paramType |
Field[] getDeclaredFelds() | Returns an array of Feld objects |
What types can have Cas objects?
Class: external class, member (member internal class, static internal class), local internal class, anonymous internal class.
interface: interface
[]: array
Enum: enum
Annotation: annotation @ interface
primitive type: basic data type
void
The object and array heap where Java memory analysis stores new can be shared by all threads without storing other object references. The variables that store the basic variable type (which will contain the specific value of the basic type) the Java memory stack reference object (which will store the specific address of the reference in the heap) can be shared by all threads. The method area contains all class and static variables
Class loading and Classloader understanding
◆ loading: load the bytecode content of Cass into memory, convert these static data into the runtime data structure of the method area, and then generate a Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java. Java Lang. class object
◆ link: the process of merging the binary code of Java class into the running state of MM.
◆ verification: ensure that the loaded class information complies with the L M specification and there are no security problems
◆ preparation: the stage of formally allocating memory for class variables (static) and setting the default initial value of class variables. These memory will be allocated in the method area.
◆ resolution: the process of replacing the symbolic reference (constant name) in 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 the assignment actions of all class variables in the class and combining the statements in the static code block during compilation. (the class constructor is used to construct class information, not the constructor to construct the class object.).
◆ when initializing a class, if it is found that its parent class has not been initialized, it is necessary to trigger the initialization of its parent class first.
◆ virtual opportunity ensures that the < clinit > (method of a class is locked and synchronized correctly in a multithreaded environment.
#Class initialization
When does class initialization occur? Active reference of class (class initialization must occur)
When the virtual machine starts, initialize the class where the main method is located first
neW - object of a class
◆ call static members (except final constants) and static methods of the class
◆ use jjava The method of Lang reflect package makes reflection calls to the class
◆ when initializing a class, if its parent class is not initialized, its parent class will be initialized first
package main.Reflection; //Active reference to class -- class initializes public class Test06 { static { System.out.println("main Method is loaded"); } public static void main(String[] args) throws ClassNotFoundException { // Son son = new Son(); //Reflections also produce references Class.forName("main.Reflection.Son"); } } class Father { static int b = 2; static { System.out.println("The parent class is being loaded"); } } class Son extends Father { static { System.out.println("Subclass loaded"); m = 300; } static int m = 100; static final int M = 1; }
Passive reference of class (class initialization will not occur)
When accessing a static domain, only
Classes that truly declare this domain will be initialized. For example, when the ◆ static variable of the parent class is referenced through the subclass, the subclass initialization will not be caused
◆ defining a class reference through an array will not trigger the initialization of this class
◆ reference constants will not trigger the initialization of this class (constants are stored in the constant pool of the calling class in the link phase)
Role of class loader
◆ function 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.xml file representing this class in the heap Lang (class) object, which serves as the access entry for class data in the method area.
◆ class cache: the standard Javase class loader can search for classes as required, but once a class is loaded into the class loader, it will remain loaded (cached) for a period of time. However, the M garbage collection mechanism can recycle these Cass objects
◆ Java Classloader (English: 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. Classes are usually loaded on demand, that is, when the class is first used. Thanks to the class loader, the Java runtime system does not need to know the file and file system. When learning class loaders, it is important to master the concept of Java delegation.
Each Java class must be loaded into memory by a class loader. Java programs can take advantage of external libraries (that is, software libraries written by other authors).
◆ there are three default class loaders in the JVM:
◆1. Bootstrap class loader. It is written by native code (such as C language) and does not inherit from Java lang.ClassLoader. Be responsible for loading the core Java library and storing it in < Java_ Home > / JRE / lib directory.
◆2. Extensions class loader. Used in < Java_ Home > / JRE / lib / ext, or Java Load the Java extension library in the directory indicated in ext.dirs. The implementation of the Java virtual machine provides an extension library directory. The class loader finds and loads Java classes in this directory. This class is created by sun misc. Launcher $extclassloader implementation.
◆3.Apps class loader (also known as system class loader). Load Java classes according to the class path of the Java application (java.class.path or CLASSPATH environment variable). Generally speaking, Java application classes are loaded by it. You can use classloader Getsystemclassloader() to get it. This class is created by sun misc. Launcher $appclassloader implementation.
◆ each class loader has a parent class loader.
package main.Reflection; public class Test07 { public static void main(String[] args) throws ClassNotFoundException { //Get system class loader // ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); // System.out.println(systemClassLoader); // //Gets the parent class loader (extension class loader) of the system class loader // ClassLoader parent = systemClassLoader.getParent(); // System.out.println(parent); // //Get the parent class loader of the extension class loader -- root loader (c,c + +) // ClassLoader parent1 = parent.getParent(); // System.out.println(parent1); // // //Test which loader loads the current class // ClassLoader classLoader = Class.forName("main.Reflection.Test07").getClassLoader(); // System.out.println(classLoader); // //Test which loader loads the jdk built-in classes // ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader(); // System.out.println(classLoader1); // // //How to get the loading path of the system class loader String property = System.getProperty("java.class.path"); System.out.println(property); //Dual delegation mechanism //java. Lang.string -- > user class loader -- > root loader //If you write a Java Lang. string, will not run, but will find the on the root loader to use /** * C:\Program Files\Java\jdk1.8.0_301\jre\lib\charsets.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\deploy.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\access-bridge-64.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\cldrdata.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\dnsns.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\jaccess.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\jfxrt.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\localedata.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\nashorn.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\sunec.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\sunjce_provider.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\sunmscapi.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\sunpkcs11.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\ext\zipfs.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\javaws.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\jce.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\jfr.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\jfxswt.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\jsse.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\management-agent.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\plugin.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\resources.jar; * C:\Program Files\Java\jdk1.8.0_301\jre\lib\rt.jar; * E:\obj\ideaObj\annotation\out\production\annotation; * D:\idear\IntelliJ IDEA 2021.2\lib\idea_rt.jar */ } }
Create an object for the runtime class
Get the complete structure of the runtime class through reflection
Field, Method, Constructor, Superclass, Interface, Annotation
All interfaces implemented
Inherited parent class
All constructors
All methods
All fields
annotation
package main.Reflection; import java.lang.reflect.Field; import java.lang.reflect.Method; //Get class information public class Test08 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("main.Reflection.User"); // User user = new User(); // c1 = user.getClass(); //Get the name of the class System.out.println(c1.getName());//Package name plus class name System.out.println(c1.getSimpleName());//Class name //Get the properties of the class System.out.println("===========Properties of class========="); Field[] fields = c1.getFields();//Only public properties can be found // for (Field field : fields) { // System.out.println(field);// Can't print out // } fields = c1.getDeclaredFields();//All properties found for (Field field : fields) { System.out.println(field); } Field name = c1.getDeclaredField("name");//Find private name from all properties // Field name1 = c1.getField("name");// Only public attribute can be found. There is no public name attribute System.out.println(name); //Acquisition method System.out.println("===========getMethods========="); Method[] methods = c1.getMethods();// Get all public methods of this class and its parent class for (Method method : methods) { System.out.println(method); } System.out.println("===========getDeclaredMethods========="); Method[] methods1 = c1.getDeclaredMethods();//Get all methods of this class for (Method method : methods1) { System.out.println(method); } } }
In the actual operation, the operation code to obtain the class information is not often developed.
Be familiar with Java Function of Lang reflect package and reflection mechanism.
How to get the names and modifiers of properties, methods and constructors.
Dynamically create object execution methods
Create Class object: call the newlnstance() method of Class object
– 1) class must have a parameterless constructor.
– 2) the access rights of the constructor of the class need to be sufficient
As long as the constructor in the class is explicitly called during the operation and the parameters are passed in, the operation can be instantiated.
The steps are as follows
– 1) get the constructor of the specified parameter type of this Class through getdeclaraedconstructor (Class.... parameterTypes) of Class class
– 2) pass an object array into the formal parameters of the constructor, which contains all the parameters required by the constructor.
3) Instantiate objects through Constructor
package main.Reflection; import java.lang.reflect.Field; //Dynamically create objects through reflection public class Test09 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException { //Get Class object Class c1= Class.forName("main.Reflection.User"); //Construct an object User user = (User)c1.newInstance();//Call parameterless constructor System.out.println(user); System.out.println("======================="); User user1 = (User)c1.newInstance();//Call parameterless constructor Field name = c1.getDeclaredField("name"); //Private properties cannot be operated directly. You need to close the program's security detection setAccessible(true) name.setAccessible(true);//Permission checking invalidates private. false is not enabled by default, and true is enabled name.set(user1,"pupil"); System.out.println(user1.getName()); } }
Call the specified method
Through reflection, the Method in the class is called and completed through the Method class
① Get a Method object through the getmethod (string name, Class. Parameter types) Method of Class class, and set the parameter type required for this Method operation.
② Then use object invoke (object obj, object [] args) to call and pass the parameter information of the obj object to be set to the method.
setAccessible
Method, Fieid and Constructor objects all have setAccessible()
The setAccessible() method is used to enable and disable access security checks
If the parameter value is true, it indicates that the Java language access check should be cancelled when the reflected object is used
– improve the efficiency of reflection. If reflection must be used in the code, and the code of this sentence needs to be called frequently, please set it to true.
– make private members that cannot be accessed can also be accessed
If the parameter value is false, it indicates that the reflected object should implement Java language access check
Performance test
package main.Reflection; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; //Analyze performance issues public class Test10 { //Normal mode call public static void test01() { User user = new User(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { user.getName(); } long endTime = System.currentTimeMillis(); System.out.println("Normal execution getName Time required for billions of times:" + (endTime - startTime) + "ms"); } //Reflection mode call public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName", null); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { getName.invoke(user, null); } long endTime = System.currentTimeMillis(); System.out.println("Reflection mode execution getName Time required for billions of times:" + (endTime - startTime) + "ms"); } //Reflection mode call public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName", null); getName.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { getName.invoke(user, null); } long endTime = System.currentTimeMillis(); System.out.println("Turn off detection reflection mode execution getName Time required for billions of times:" + (endTime - startTime) + "ms"); } public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { test01(); test02(); test03(); } }
Get generic information
Reflection operation generics
Java uses the generic erasure mechanism to introduce generics. Generics in Java are only used by the compiler javac to ensure data security and avoid forced type conversion. However, once the compilation is completed, all types related to generics are erased
In order to manipulate these types through reflection, Java adds parameterizedtype and genericarray type. TypeVariable and WildcardType are several types to represent types that cannot be classified into Class but have the same name as the original type
Parametrizedtype: indicates a parameterized type; For example, collection < string >
GenericArrayType: indicates that - element types are parameterized types or array types of type variables
TypeVariable: it is the public parent interface of various types of variables
WildcardType: represents a wildcard type expression
package main.Reflection; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; //Get generics through reflection public class Test11 { public void test01(Map<String, User> map, List<User> list) { System.out.println("01"); } public Map<String, User> test02() { System.out.println("02"); return null; } public static void main(String[] args) throws NoSuchMethodException { Method me = Test11.class.getMethod("test01", Map.class, List.class); Type[] genericParameterTypes = me.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println(genericParameterType); if (genericParameterType instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println("##" + actualTypeArgument); } } } me = Test11.class.getMethod("test02", null); Type genericReturnType = me.getGenericReturnType(); if (genericReturnType instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println("##" + actualTypeArgument); } } } }
Get annotation information
Reflection operation annotation
getAnnotations
getAnnotation
package main.Reflection; import java.lang.annotation.*; import java.lang.reflect.Field; //Contact reflection operation annotation public class Test12 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("main.Reflection.Student2"); //Get annotations through reflection Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //Get the value of annotation value TableCloud tableCloud = (TableCloud) c1.getAnnotation(TableCloud.class); String value = tableCloud.value(); System.out.println(value); //Gets the annotation specified by the class Field f = c1.getDeclaredField("id"); FieldCloud annotation = f.getAnnotation(FieldCloud.class); System.out.println(annotation.conlumnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); } } @TableCloud("db_student") class Student2 { @FieldCloud(conlumnName = "db_id", type = "int", length = 10) private int id; @FieldCloud(conlumnName = "db_age", type = "int", length = 10) private int age; @FieldCloud(conlumnName = "db_name", type = "String", length = 3) private String name; public Student2() { } public Student2(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; } } //Class name annotation @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface TableCloud { String value(); } //Attribute annotation @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface FieldCloud { String conlumnName(); String type(); int length(); }