Reflection mechanism and Application
What is reflection
In the program running state, for any class or object, all properties and methods of the class (including private properties and methods) can be obtained. This function of dynamically obtaining information and dynamically calling object methods is called reflection mechanism. In short, through reflection, classes are completely transparent to us. You can get anything you want.
Class object
Every Class we create is also an object, that is, the Class itself is Java Instance object of lang.Class class. This instance object is called a Class object, that is, a Class object.
The instance object of Class represents the classes and interfaces in the running Java application, that is, each instance in the JVM. Each Class has a unique Class
object
Class class has no public construction method. Class object is automatically constructed by Java virtual machine when loading class
The Class object is used to provide information about the Class itself, such as how many construction methods there are, how many attributes there are, and what common methods there are
Three ways to get Class objects
It can be obtained in the source code phase. Class.forName("full class name"). Load the bytecode file into memory and return the class object, which is mostly used in the configuration file and the configuration file defined by the class name.
Get the class name in the class object phase class. This method is mostly used for parameter transfer
Get: new class name () in the Runtime stage getClass(). This method is defined in the Object class (all classes inherit from Object), so all classes will inherit this method. It is mostly used to obtain bytecode from objects.
Get Class object case
public class GetClass { @Test public void classForName() throws ClassNotFoundException { // Mode 1 class Forname ("full class name") final Class<?> clazz1 = Class.forName("cn.wujiwen.basic.reflect.ExampleClass"); System.out.println("class1:" + clazz1); } @Test public void nameClass(){ // Mode II name class final Class<ExampleClass> clazz2 = ExampleClass.class; System.out.println("class2:" + clazz2); } @Test public void ObjectGetClass(){ // Method 3: instance object getClass() ExampleClass exampleClass = new ExampleClass(); Class<?> clazz3 = exampleClass.getClass(); System.out.println("class3:" + clazz3); } // The same section code file (*. class) will only be loaded once during a program run. The class object obtained by either method is the same. @Test public void all() throws ClassNotFoundException { Assertions.assertSame(Class.forName("cn.wujiwen.basic.reflect.ExampleClass") , ExampleClass.class); } }
Function of Class object
Here we will briefly record three common functions. For more methods, you can read the class source code completely
1. Get member variable
//Gets the member variables of all public modifiers Field[] getFields() //Gets the member variable of the public modifier with the specified name Field getField(String name) //Gets all member variables, regardless of modifiers Field[] getDeclaredFields() //Gets the specified member variable, regardless of the modifier Field getDeclaredField(String name)
2. Get construction method
//Get constructors for all public modifiers Constructor<?>[] getConstructors() //Gets the constructor of the specified public modifier Constructor<T> getConstructor(class<?>... parameterTypes) //Get all constructors, regardless of modifiers Constructor<?>[] getDeclaredConstructors() //Gets the specified constructor, regardless of modifiers Constructor<T> getDeclaredConstructor(class<?>... parameterTypes) //Gets the specified constructor, regardless of modifiers
3. Get member method
//Gets the member method of all public modifiers Method[] getMethods() //Gets the member method of the public modifier with the specified name Method getMethod(String name, class<?>... parameterTypes) //Gets all member methods, regardless of modifiers Method[] getDeclaredMethods() //Gets the member method of the specified name, regardless of the modifier Method getDeclaredMethod(String name, class<?>... parameterTypes)
Let's test one class by one. First, prepare the class and attribute information required by the above functional methods
public class ExampleClass { // public decorated properties public String publicField; // private decorated properties private String privateField; // default String defaultField; // protected modified house type protected String protectedField; // The protected parameterless construction conflicts with the public parameterless construction, and the overwrite operation will occur protected ExampleClass(){ } // public is a parameter constructor public ExampleClass(String privateField){ this.privateField = privateField; } public void publicMethod(){ } private void privateMethod(){ } protected void protectedMethod(){ } void defaultMethod(){ } public void noParamsMethod(){ System.out.println("this is noParamsMethod"); } public void paramsMethod(String params){ System.out.println("this is paramsMethod,params is " + params); } }
Next, we will test the use and permission information of each function
Get member variable
@Test public void getField() throws NoSuchFieldException { Class<ExampleClass> exampleClassClass = ExampleClass.class; Field[] fields = exampleClassClass.getFields(); System.out.println(Arrays.asList(fields)); // Only one public attribute information is returned // [public java.lang.String cn.wujiwen.basic.reflect.ExampleClass.publicField] Field publicField = exampleClassClass.getField("publicField"); System.out.println(publicField); // It can be obtained. If it is set to other attribute parameters, an error will be reported // public java.lang.String cn.wujiwen.basic.reflect.ExampleClass.publicField Field[] declaredFields = exampleClassClass.getDeclaredFields(); System.out.println(Arrays.asList(declaredFields)); // All attribute information is returned, regardless of modifier information // [public java.lang.String cn.wujiwen.basic.reflect.ExampleClass.publicField, private java.lang.String cn.wujiwen.basic.reflect.ExampleClass.privateField, java.lang.String cn.wujiwen.basic.reflect.ExampleClass.defaultField, protected java.lang.String cn.wujiwen.basic.reflect.ExampleClass.protectedField] Field privateField = exampleClassClass.getDeclaredField("privateField"); System.out.println(Arrays.asList(privateField)); // private java.lang.String cn.wujiwen.basic.reflect.ExampleClass.privateField }
Get constructor
@Test public void getConstructor() throws NoSuchMethodException { Class<ExampleClass> exampleClassClass = ExampleClass.class; Constructor<?>[] constructors = exampleClassClass.getConstructors(); System.out.println(Arrays.toString(constructors)); // [public cn.wujiwen.basic.reflect.ExampleClass(java.lang.String)] Constructor<ExampleClass> constructor = exampleClassClass.getConstructor(String.class); System.out.println(constructor); // public cn.wujiwen.basic.reflect.ExampleClass(java.lang.String) Constructor<?>[] declaredConstructors = exampleClassClass.getDeclaredConstructors(); System.out.println(Arrays.toString(declaredConstructors)); // [public cn.wujiwen.basic.reflect.ExampleClass(java.lang.String), protected cn.wujiwen.basic.reflect.ExampleClass()] Constructor<ExampleClass> declaredConstructor = exampleClassClass.getDeclaredConstructor(null); System.out.println(declaredConstructor); // protected cn.wujiwen.basic.reflect.ExampleClass() }
Get member method
@Test public void getMethod() throws Exception { Class<ExampleClass> exampleClassClass = ExampleClass.class; Method[] methods = exampleClassClass.getMethods(); System.out.println(Arrays.toString(methods)); // Returns all public information, including wait and other method information in the Object class // [public void cn.wujiwen.basic.reflect.ExampleClass.publicMethod(), public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()] Method publicMethod = exampleClassClass.getMethod("publicMethod"); System.out.println(publicMethod); // public void cn.wujiwen.basic.reflect.ExampleClass.publicMethod() Method[] declaredMethods = exampleClassClass.getDeclaredMethods(); System.out.println(Arrays.toString(declaredMethods)); // Only all methods in this class are returned // [private void cn.wujiwen.basic.reflect.ExampleClass.privateMethod(), public void cn.wujiwen.basic.reflect.ExampleClass.publicMethod(), protected void cn.wujiwen.basic.reflect.ExampleClass.protectedMethod(), void cn.wujiwen.basic.reflect.ExampleClass.defaultMethod()] Field protectedField = exampleClassClass.getDeclaredField("protectedField"); System.out.println(protectedField); // protected java.lang.String cn.wujiwen.basic.reflect.ExampleClass.protectedField Method enclosingMethod = exampleClassClass.getEnclosingMethod(); System.out.println(enclosingMethod); // null has no internal anonymous method orz }
Function of Field object
Common functions usually include obtaining attribute values, assigning new values, etc
@Test public void modifyField() throws Exception { ExampleClass exampleClass = new ExampleClass(); Class<? extends ExampleClass> classClass = exampleClass.getClass(); Field publicField = classClass.getField("publicField"); Object publicFieldValue = publicField.get(exampleClass); System.out.println(publicFieldValue); Field privateField = classClass.getDeclaredField("privateField"); // //Ignore the check of access rights, violent reflection privateField.setAccessible(true); // Get value Object privateFieldVale = privateField.get(exampleClass); System.out.println(privateFieldVale); // Assign new value privateField.set(exampleClass,"newPrivateValue"); Object newValue = privateField.get(exampleClass); System.out.println(newValue); }
Function of Method object
Execute the method Object invoke(Object obj,Object... args);
Get parameter getParameters()
@Test public void methodFun() throws Exception { ExampleClass exampleClass = new ExampleClass(); Class<? extends ExampleClass> classClass = exampleClass.getClass(); Method noParamsMethod = classClass.getMethod("noParamsMethod"); // Execution method noParamsMethod.invoke(exampleClass); Method paramsMethod = classClass.getMethod("paramsMethod", String.class); // Get parameters Parameter[] parameters = paramsMethod.getParameters(); System.out.println(Arrays.toString(parameters)); // Execution method paramsMethod.invoke(exampleClass,"This is a parameter"); }
extend
In the process of sorting out field, method and constructor, we found that they all inherit from the AccessibleObject class, setAccessible(true) mentioned above; Method is a function provided by this class. The following also introduces a very common annotation function in the framework. In reflection, we can obtain the annotations of the above three objects, and then complete more customization functions
First, we add the annotation information in the jdk in ExampleClass and try to obtain the annotation information by reflection
@Deprecated public class ExampleClass { // public decorated properties @Deprecated public String publicField; @Deprecated public void publicMethod(){ } }
We add a common out of date annotation to the class name attribute and method respectively
@Test public void getAnnotation() throws Exception { ExampleClass exampleClass = new ExampleClass(); Class<? extends ExampleClass> classClass = exampleClass.getClass(); Annotation[] classAnnotations = classClass.getDeclaredAnnotations(); System.out.println(Arrays.toString(classAnnotations)); Field publicField = classClass.getField("publicField"); Annotation[] fieldAnnotations = publicField.getAnnotations(); System.out.println(Arrays.toString(fieldAnnotations)); Method publicMethod = classClass.getMethod("publicMethod"); Deprecated annotation = publicMethod.getAnnotation(Deprecated.class); System.out.println(annotation); }
In this way, we can get the annotation information on the related objects.
Practical application
Above, we have listed many common functions and usages in reflection in combination with cases. Below, we will apply the above functions in development practice in combination with a simple functional requirement. Because they are simple applications, they are not used as actual development references.
Function description
Now we have a set of parsed complete data (read through excel or xml, etc.), which need to be assembled into the corresponding object according to the requirements for later application. For example, we have several sets of statistical data, one is the school's student information data, the other is the school's teacher information data, It has been parsed from the three-party table through the parsing tool and encapsulated into an array set. The data corresponding to the array index is known, such as the representative name of index=0
Let's get the data ready first
List<List<Object>> teachers = new ArrayList<>(); List<List<Object>> students = new ArrayList<>(); @BeforeEach public void data(){ List<Object> teacher1 = new ArrayList<>(); teacher1.add("Miss Zhang"); teacher1.add(20); teacher1.add("13011111111"); teacher1.add("language"); List<Object> teacher2 = new ArrayList<>(); teacher2.add("Miss Li"); teacher2.add(40); teacher2.add("13811111111"); teacher2.add("mathematics"); teachers.add(teacher1); teachers.add(teacher2); List<Object> student1 = new ArrayList<>(); student1.add("Li Hua"); student1.add(10); student1.add("Class 1, grade 3"); List<Object> student2 = new ArrayList<>(); student2.add("Tie Zhu Zhao"); student2.add(11); student2.add("Class 2, grade 4"); students.add(student1); students.add(student2); }
[[Mr. Zhang, 20, 13011111111, Chinese], [Mr. Li, 40, 13811111111, mathematics]]
[[Li Hua, grade 10, class 1, grade 3], [Zhao Tiezhu, grade 11, class 2, grade 4]]
Now there are two classes, Student and Teacher, which need to receive the corresponding data information
public class Student { /** * Student name */ private String studentName; /** * Class name */ private String className; /** * Age */ private Integer age; // setter getter ... } public class Teacher { private String name; private String mobile; private String subject; private Integer age; // setter getter ... }
Next, we will put the above two sets of inputs into the corresponding objects through reflection, and accurately correspond to their respective attributes
We can customize the annotation, apply the annotation content to each field, mark the specific index value of the field in the array, and then assign it to the field.
Customize a field index annotation
@Retention(RetentionPolicy.RUNTIME) @Target(value = {FIELD}) public @interface FieldIndex { /** * Corresponding index * @return */ int index(); } reform Student and Teacher class java public class Student { /** * Student name */ @FieldIndex(index = 0) private String studentName; /** * Class name */ @FieldIndex(index = 2) private String className; /** * Age */ @FieldIndex(index = 1) private Integer age; } public class Teacher { @FieldIndex(index = 0) private String name; @FieldIndex(index = 2) private String mobile; @FieldIndex(index = 3) private String subject; @FieldIndex(index = 1) private Integer age; }
Define a tool method
/** * * @param t Class to bind * @param data Processed data * @param <T> * @return */ public <T> void bind(T t,List<Object> data){ Class<?> clazz = t.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { // Gets the annotation of the field FieldIndex annotation = field.getAnnotation(FieldIndex.class); // Valid annotation if (annotation != null && annotation.index() >= 0){ // Gets the index value in the annotation int index = annotation.index(); // Get data in data Object value = data.get(index); // Ignore check field.setAccessible(true); // Copy to this field try { field.set(t,value); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }
test
@Test public void dataBind(){ List<Teacher> teacherList = new ArrayList<>(); for (List<Object> teacherArr : teachers) { Teacher teacher = new Teacher(); bind(teacher,teacherArr); teacherList.add(teacher); } List<Student> studentList = new ArrayList<>(); for (List<Object> studentArr : students) { Student student = new Student(); bind(student,studentArr); studentList.add(student); } System.out.println(teacherList); System.out.println(studentList); }
In this way, we have completed a simple data binding. There are many extensions of similar functions, such as data verification on a sub basis. In our actual development process, there are many such processing methods. The use of reflection mechanism can greatly facilitate our development.
Finally, I wish you all success in your studies and satisfaction offer , fast promotion increase , go to the peak of life.
If you can, please give me a three company to support me??? [white whoring data]