0. Concept
Reflection Library: a collection of tools that can be used to write programs that dynamically manipulate Java code.
Reflection: a program that can analyze the ability of classes, which can be used to
- The ability to analyze classes at run time
- Check objects at run time
- Implementation of generic array operation code
- Using Method objects
1. class
1.1 concept
Runtime type identification: the java runtime system always maintains a runtime type identification for all objects. This information will track the class to which each object belongs
Class: use a special java class to access this information (runtime type ID). The class name that saves this information is class
1.2 three methods to obtain Class objects
a. Object.getClass method: this method will return an instance of Class type
Employee e;
Class c1 = e.getClass();
The Class object will describe the properties of a specific Class. As described above, c1 can describe the properties of the Class Employee. The most common method is getName(), which will return the name of the Class
e.getClass().getName()
b. Static method forName: get the Class object corresponding to the type
String className = "java.util.Random";
Class c1 = Class.forName();
Only when className is a class name or interface name can this method execute normally, and an exception handler should be provided whenever it is used
c. If T is an arbitrary Java type, T.class will represent the matching class object
For example:
Class cl1 = Random.class; Class cl2 = int.class; Class cl3 = Double[].class;
Note: a Class object actually represents a type, which may or may not be a Class. For example, int is not a Class and int.class is an object of Class type
1.3 use = = operation to compare the objects of two classes
The virtual machine manages a unique Class object for each type
For example:
if (e.getClass == Employee.class)
1.4 construct an instance of a description class
If you have an object of Class type, you can use it to construct an instance of the Class
try { String className = "java.util.Random"; Class c1 = Class.forName(className); Object obj = c1.getConstructor().newInstance(); System.out.println(obj); } catch (Exception e) { e.printStackTrace(); }
Output:
2. Ability to use reflection analysis class
You can check the structure of the class.
java. In lang.reflect, there are three classes: file, Method and Constructor, which are used to describe the fields, methods and constructors of the class respectively
The three classes share a getName() method that returns the name of a field, method, or constructor.
The following code uses the api of Class to print all the information of a Class
public class ReflectionTest { public static void main(String[] args) throws ClassNotFoundException { //Read the class name from the command terminal or user input String name; if (args.length>0) { name = args[0]; }else { Scanner in = new Scanner(System.in); System.out.println("Enter class name (e.g. java.util.Date):"); name = in.next(); } //Print the class name and parent class name (not Object (in case of) Class cl = Class.forName(name); Class superclass = cl.getSuperclass(); //getModifiers Returns an integer describing the modifier used, using Modifier.toString Method to print the modifier String modifier = Modifier.toString(cl.getModifiers()); if (modifier.length()>0) { System.out.print(modifier+" "); } System.out.print("class "+name); if (superclass !=null && superclass != Object.class) { System.out.print(" extends "+superclass.getName()); } System.out.print("\n{\n"); //Print constructor printConstructors(cl); System.out.println(""); printMethods(cl); System.out.println(""); printFiled(cl); System.out.println("}"); } //Print all constructors of this class public static void printConstructors(Class cl){ //getDeclaredConstructors: Get all constructors Constructor[] constructors = cl.getDeclaredConstructors(); for (Constructor c : constructors) { //Gets the name of the constructor String name = c.getName(); System.out.print(" "); //Gets the modifier of the constructor String modifier = Modifier.toString(c.getModifiers()); if (modifier.length()>0) { System.out.print(modifier+" "); } System.out.print(name+"("); //Print parameter type Class[] parameterTypes = c.getParameterTypes(); for (int i = 0; i <parameterTypes.length ; i++) { if (i>0) { System.out.print(", "); } System.out.print(parameterTypes[i].getName()); } System.out.println(");"); } } //Print all methods public static void printMethods(Class c1){ Method[] methods = c1.getMethods(); for (Method m : methods) { //Return type Class retType = m.getReturnType(); String name = m.getName(); System.out.print(" "); String modifier = Modifier.toString(m.getModifiers()); if (modifier.length()>0) { System.out.print(modifier+" "); } System.out.print(retType.getName()+" "+name+"("); //Print all parameter types Class[] parameterTypes = m.getParameterTypes(); for (int i = 0; i <parameterTypes.length ; i++) { if (i>0) { System.out.print(", "); } System.out.print(parameterTypes[i].getName()); } System.out.println(");"); } } public static void printFiled(Class cl){ Field[] fields = cl.getDeclaredFields(); for (Field f : fields) { Class type = f.getType(); String name = f.getName(); System.out.print(" "); String modifiers = Modifier.toString(f.getModifiers()); if (modifiers.length() > 0) { System.out.print(modifiers+" "); } System.out.println(type.getName()+" "+name+";"); } } }
3. Use reflection to analyze objects at run time
- Using the reflection mechanism, you can view object fields that are not known during compilation
- The access to fields is affected by Java security control. The default behavior of the reflection mechanism is limited by Java access control, but you can call the setAccessible method of Field to override Java access control, for example:
f.setAccessible(true);
4. Write generic array code using reflection
java. The Array class in lang.reflect package allows dynamic Array creation
For example, the implementation of CopyOf:
public static Object goodCopyOf(Object a,int newlength){ //obtain a Class object of array Class cl = a.getClass(); if(!cl.isArray()) return null; //Determine the correct type of array Class componentType = cl.getComponentType(); int length = Array.getLength(a); Object newArray = Array.newInstance(componentType, newlength); System.arraycopy(a,0,newArray,0,Math.min(length,newlength)); return newArray; }
5. Use reflection to call methods and constructors
The reflection mechanism allows you to call any Method. There is an invoke Method in the Method class, which allows you to call the Method of the current Method object
Method m1 = Math.class.getMethod("sqrt", double.class); double d =(Double) m1.invoke(null, 4); System.out.println(d);
Output: