Explore the Java reflection mechanism
Java reflection mechanism can be said that we usually use a lot of development, although as developers, we do not feel anything, it is because the framework designers have encapsulated for us, we just need to call it. I have also used reflection in the past, including myself and I have learned it, but I feel a little lighter. Today I have time and I think it is necessary to take a deeper look at it.
We call the program capable of analyzing the class capability reflective. The reflection mechanism and its powerful functions are as follows:
1. Ability to analyze classes during running;
2. view the object in the running state. For example, compile a general tostring method;
3. implement common array operation code;
4. Use the Method object;
In fact, reflection is very easy to use. We only need to remember that the first step of Using Reflection is to get the Class, so what is this Class? We should note that this Class is different from the class, class represents a type, a keyword. It is the basic element in Java. We all know that common classes in Java are modified by class, while enumeration is modified by enum. Our Class indicates:
During the running of the program, the Java System maintains a runtime type identifier for all the objects in the club. This information tracks the class to which each object belongs. We store all information about this Class in the Class. As long as we obtain the Class, we can obtain the desired result based on its specific method;
I don't know much about the Class here. We just need to remember that the Class is like the key to open the treasure. It contains the classes, objects, methods, constructors we need, but if there is no such key, everything is useless. So we need to construct the Class first;
Let's take a look at three methods to construct a Class;
1. Class. forName (Class Name string) (Note: The Class name string must be the full name, package name + Class name)
2. class Name. class
3. Instance Object. getClass ()
Create a simple Person class first;
Public class Person implements Serializable {private int id; public String name; protected String address; int age; static {System. out. println (static initialization block);} {System. out. println (fast initialization );}
Omit basic methods such as get, set, and constructor. Let's test it;
Public static void main (String [] args) {try {Class c1 = Class. forName (com.cn. vo. person); // obtain the Class through the Class name, and the package name also belongs to part of the Class name Class c2 = Person. class; // obtain ClassPerson p = new Person () through the Class object; class c3 = p. getClass (); // obtain ClassSystem through object reference. out. println (c1); System. out. println (c2); System. out. println (c3); System. out. println (c1 = c3);} catch (ClassNotFoundException e) {e. printStackTrace ();}}
It is the simplest way to get a Class through a Class object, but note that a Class Object actually represents a type, And this type is not necessarily a type, for example, int Is not a class, but int. A class is an object of the Class type.
However, no matter which method is used, we can only get one Class at the end, because our static initialization block is only executed once, proving that our Class is loaded only once.
Therefore, the process of generating Class objects is actually as follows:
When we compile a new java class, JVM will compile it into a class object and store it in a. class file with the same name. During runtime, when an object of this class needs to be generated, JVM will check whether the class has been loaded into memory. If it is not loaded, load the. class file into the memory. If it is loaded, the instance object is generated based on the class file. From this we can draw a conclusion that a java Class has only one Class.
This is mainly because the ClassLoader uses the parent-parent delegation mechanism. Before a custom ClassLoader loads a class, it will first delegate its parent ClassLoader to load the class, only when the parent ClassLoader cannot be loaded successfully will it be loaded by itself; let's take a look at the source code:
Protected synchronized Class loadClass (String name, boolean resolve) throws ClassNotFoundException {// first check whether the class specified by this name has been loaded Class c = findLoadedClass (name ); if (c = null) {try {if (parent! = Null) {// If parent is not null, call the loadClass of parent to load = parent. loadClass (name, false);} If else {// parent is null, call BootstrapClassLoader to load c = findBootstrapClass0 (name);} catch (ClassNotFoundException e) {// if the load still fails, call its findClass to load c = findClass (name) ;}} if (resolve) {resolveClass (c) ;}return c ;}Well, the final conclusion is that no matter what method we use, we only need to get a Class, which means there is only one key to open the treasure, this is not the most important way to get it by any means. The key is to open the door to the treasure;
Since we get the Class, we can use it to get a lot of things;
Here we use the reflection class and reflect's API method to print all the information of a class;
The main APIs are described as follows:
Field Class: represents the member variables of the class (member variables are also called the attributes of the class ). Method class: indicates the Method of the class. Constructor class: Constructor class. Array class: provides static methods for dynamically creating arrays and accessing Array elements.
Below are a few small examples to flexibly use the Java reflection mechanism.
Print the complete information of a class. The following method prints the class package name, class name, method name and all domain names;
Try {String s = com.cn. vo. person; Class c1 = Class. forName (s); // obtain ClassStringBuffer sb = new StringBuffer (package) by using the class name; // construct the keyword sb for the package name. append (c1.getPackage (). getName () ++); // get the package name sb. append (Modifier. toString (c1.getModifiers () + class + c1.getSimpleName () + {+); // get the class modifier and class Name Field [] file = c1.getDeclaredFields (); // obtain all attributes for (Field f: file) {sb. append (Modifier. toString (f. getModifiers () +); // get the modifier sb. append (f. getType (). getSimpleName () +); // get the variable type sb. append (f. getName () +;); // get the variable name sb. append ();} Method [] methods = c1.getDeclaredMethods (); // obtain all the methods for (Method m: methods) {Class retType = m. getReturnType (); // obtain the sb type of the method. append (Modifier. toString (m. getModifiers () +); // get the modifier sb. append (retType +); sb. append (m. getName () +;); // obtain the method name sb. append ();} sb. append (});} catch (Exception e) {e. printStackTrace ();}
No get or set method class for access settings;
We usually have the get and set methods for developing a javabean. But if there is no get or set method, how can we get its value and change its value, we can use Java reflection technology;
Try {Person p = new Person (James, Xiangyang, Hubei, 23); Class c2 = p. getClass (); Field f = c2.getDeclaredField (address); // obtain the domain name f. setAccessible (true); // if it is set to true, you can also access the private class; Object st = f. get (p); // obtain the domain name value f. set (p, Wuhan); // reset the value System. out. println (p);} catch (Exception e) {e. printStackTrace ();}Here is a Method called setAccessible, which is a public superclass of the Field, Method, and Constructor classes. This feature is provided by debugging, persistent storage, and similar mechanisms. To access the private modified class, you must set it to true;
Design a general toString method;
Public static String toString (Object obj) {if (obj = null) return null; Class c1 = obj. getClass (); if (c1 = String. class) return (String) obj; // if the passed object is a String object, the result is printed directly. StringBuffer st = new StringBuffer (); try {if (c1.isArray ()) {// array object st. append (c1.getComponentType () + [] {); // type for (int I = 0; i0) st. append (,); Object val = Array. get (obj, I); // The cyclic value is st. append (val);} return st. append (}). toString ();} // The parent class of each class is an Object. Print; while (c1.getSuperclass ()! = Null &&! C1.getSimpleName (). equals (Object) {st. append (c1.getName () + [); // Class Name Field [] fields = c1.getDeclaredFields (); // obtain all the attributes AccessibleObject. setAccessible (fields, true); // you can specify the ACL for a private attribute for (Field f: fields) {if (! St. toString (). endsWith ([) st. append (,); st. append (f. getName () + =); // print and obtain the attribute name Object val = f. get (obj); // get the attribute value st. append (val);} st. append (]); c1 = c1.getSuperclass (); // obtain the parent class and Recursion up;} catch (Exception e) {e. printStackTrace ();} return st. toString ();}Despite the powerful reflection mechanism, we can write more universal programs, but we still need to use less reflection when developing modules on a daily basis, because reflection is more fragile and not prone to troubleshooting. Today, we will explore the connection between spring, struts, and reflection next time.