Catalog
I. What is Reflection
In the running state, for any class, all its attributes and methods can be known, and for any object, any method and attributes can be invoked. This ability to dynamically obtain information and invoke methods is called the reflection mechanism of Java language. Most frameworks use reflection mechanism to understand reflection. The method of use is very important.
A class usually contains attributes, methods, constructors and so on. Java usually has objects in existing classes. It calls various attributes and methods through objects, while Java reflection obtains information about its classes and calls related methods of its classes through existing objects.
II. Basic Class of Reflection
2.1 Class class overview
We know that in the Java world, everything is an object. In fact, the class itself is an object, and any class is an instance object of the Class class.
//Define a SuperHero class public class SuperHero {}
As defined above, SuperHero classes are classes and objects.
Object: SuperHero class is an instance of Class class, Class class is the class type of SuperHero, so it is an object.
Class: Created as a class, SuperHero itself can call SuperHero ironMan = new SuperHero () to be instantiated. IronMan is the entity created, so it is also a class.
Class class is very special. It represents the class type of a class and can not be inherited. There is only one Class object for each class. Class class has no common constructor. Instead, Class objects are built automatically by the Java virtual machine because classes are loaded, and are represented as Class objects by calling the defineClass method in the class loader, the original Java types (boolean, byte, char, short, int, long, float and double), and the keyword void.
//Class source code, final modifier can not be inherited, constructor is private, can not be instantiated manually public final class Class<T> { private Class(ClassLoader loader) { // Initialize final field for classLoader. The initialization value of non-null // prevents future JIT optimizations from assuming this final field is null. classLoader = loader; } }
public static void main(String[] args) { try { Class clazz1 = Class.forName("java.lang.Integer"); Class clazz2 = Class.forName("java.lang.Integer"); System.out.println(clazz1 == clazz2); System.out.println(int.class); System.out.println(void.class); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
The results are as follows:
true int void
2.2 Three Ways of Obtaining Class Class Objects
Define a class first
package reflectdemo; import java.io.Serializable; /** * Superheroes */ public class SuperHero implements Serializable { public static final String ADDRESS = "earth"; private String id; private String name; private Integer age; private String skill; public SuperHero() { } public SuperHero(String id, String name, Integer age, String skill) { this.id = id; this.name = name; this.age = age; this.skill = skill; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getSkill() { return skill; } public void setSkill(String skill) { this.skill = skill; } public void print(){ System.out.println("Superhero Movie:" + this.name); } }
2.2.1 Getting Class from Objects
public static void main(String[] args) { SuperHero ironMan = new SuperHero("1","Iron Man",35, "War armor"); Class clazz = ironMan.getClass(); System.out.println(clazz.getName()); }
Output results:
reflectdemo.SuperHero
2.2.2 Get Class by Class
public static void main(String[] args) { Class clazz = SuperHero.getClass(); System.out.println(clazz.getName()); }
Output results:
reflectdemo.SuperHero
2.2.3 Input Class Path to Get Class
public static void main(String[] args) { try { Class clazz = Class.forName("reflectdemo.SuperHero"); System.out.println(clazz.getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
Output results:
reflectdemo.SuperHero
There are three ways to create:
The first way is that the object already exists, and all operations can be done directly through the object.
The second way requires import to introduce classes, which is not the usual way.
The third way is to get the relevant information of the class only by passing in the path of the class, which is the most commonly used way.
2.2.4 Common methods for obtaining class information
public static void main(String[] args) { try { Class clazz = Class.forName("reflectdemo.SuperHero"); //Get the class name (with path) System.out.println(clazz.getName()); //Get the class name (without paths) System.out.println(clazz.getSimpleName()); //Get the package in question System.out.println(clazz.getPackage()); //Create objects through Class SuperHero hero = (SuperHero)clazz.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
Output results:
reflectdemo.SuperHero SuperHero package reflectdemo
Let me explain in advance that two methods in Class have the same functions. If one of them has the word Declared, which means all declared variables, methods, constructors, etc. in the class, and the corresponding method without the word Declared, it means that only public member variables and methods work, and the following is not repeated. Description, below is only a description of the method with the word Declared.
3. Reflection-constructor
3.1 getDeclaredConstructor(Class<?>...parameterTypes)
public class ClassUtils { /** * Get the constructor * @param clazz class * @param params Constructor parameter type * @throws NoSuchMethodException */ public static void getDeclaredConstructor(Class clazz, Class[] params) throws NoSuchMethodException { System.out.println(clazz.getDeclaredConstructor(params)); } } public class ClassTest { public static void main(String[] args) { try { Class clazz = Class.forName("reflectdemo.SuperHero"); //Print parametric constructor ClassUtils.getDeclaredConstructor(clazz, null); //Printed parametric constructor ClassUtils.getDeclaredConstructor(clazz, new Class[]{String.class, String.class, Integer.class, String.class}); } catch (Exception e) { e.printStackTrace(); } } }
The output results are as follows:
public reflectdemo.SuperHero() public reflectdemo.SuperHero(java.lang.String,java.lang.String,java.lang.Integer,java.lang.String)
3.2 getDeclaredConstructors()
public class ClassUtils { /** * Ergodic constructor * @param clazz class */ public static void getDeclaredConstructors(Class clazz){ //Get all constructors Constructor[] constructors = clazz.getDeclaredConstructors(); for (Constructor constructor : constructors) { //Direct Print Constructor System.out.println(constructor); //Print constructor name System.out.println(constructor.getName()); //Print constructor parameters Parameter[] parameters = constructor.getParameters(); for(Parameter parameter : parameters){ System.out.print(parameter); System.out.print(", "); } System.out.println("---------------------"); } } } public class ClassTest { public static void main(String[] args) { try { Class clazz = Class.forName("reflectdemo.SuperHero"); //Ergodic constructor ClassUtils.getDeclaredConstructors(clazz); } catch (Exception e) { e.printStackTrace(); } } }
The output results are as follows:
public reflectdemo.SuperHero() reflectdemo.SuperHero --------------------- public reflectdemo.SuperHero(java.lang.String,java.lang.String,java.lang.Integer,java.lang.String) reflectdemo.SuperHero java.lang.String arg0, java.lang.String arg1, java.lang.Integer arg2, java.lang.String arg3, ---------------------
Reflection-member variables
4.1 getDeclaredField(String name)
public class ClassUtils { /** * Get property fields * @param clazz class * @param fieldName Property name * @throws Exception */ public static void getDeclaredField(Class clazz, String fieldName) throws Exception{ System.out.println(clazz.getDeclaredField(fieldName)); } } public class ClassTest { public static void main(String[] args) { try { Class clazz = Class.forName("reflectdemo.SuperHero"); //Testing public attributes ClassUtils.getDeclaredField(clazz, "ADDRESS"); //Testing private properties ClassUtils.getDeclaredField(clazz, "name"); } catch (Exception e) { e.printStackTrace(); } } }
The output results are as follows:
public static final java.lang.String reflectdemo.SuperHero.ADDRESS private java.lang.String reflectdemo.SuperHero.name
4.3 getDeclaredFields()
public class ClassUtils { /** * Traversing through existing member variables of clazz objects * @param clazz */ public static void getDeclaredFields(Class clazz){ Field[] fields = clazz.getDeclaredFields(); for (Field field: fields) { //If you want to set values, you need to add the following sentence: Reflective objects do not use Java language access checks when they are used //field.setAccessible(true); //Direct Printing Field System.out.println(field); //Manual acquisition of variable type and variable name System.out.println(field.getType().getName() + " " +field.getName()); System.out.println("--------------------"); } } } public class ClassTest { public static void main(String[] args) { try { Class clazz = Class.forName("reflectdemo.SuperHero"); //Traversing member variables ClassUtils.getDeclaredFields(clazz); } catch (Exception e) { e.printStackTrace(); } } }
The output results are as follows:
public static final java.lang.String reflectdemo.SuperHero.ADDRESS java.lang.String ADDRESS -------------------- private java.lang.String reflectdemo.SuperHero.id java.lang.String id -------------------- private java.lang.String reflectdemo.SuperHero.name java.lang.String name -------------------- private java.lang.Integer reflectdemo.SuperHero.age java.lang.Integer age -------------------- private java.lang.String reflectdemo.SuperHero.skill java.lang.String skill --------------------
V. Reflection-Membership Method
5.1 getDeclaredMethod(String name, Class<?>... parameterTypes)
public class ClassUtils { /** * Getting membership methods * @param clazz class * @param methodName Method name * @param params parameter list * @throws Exception */ public static void getDeclaredMethod(Class clazz, String methodName, Class[] params) throws Exception{ Method method = clazz.getDeclaredMethod(methodName, params); System.out.println("Direct Printing"); System.out.println(method); System.out.println("Manual Construction"); //Get the return type System.out.print(method.getReturnType().getSimpleName() + " "); //Get the method name System.out.print(method.getName() + "("); //Get the parameter type Class[] paramTypes = method.getParameterTypes(); for(int i = 0; i < paramTypes.length; i++){ Class param = paramTypes[i]; if(i < paramTypes.length - 1){ System.out.print(param.getSimpleName() + ", "); }else { System.out.print(param.getSimpleName()); } } System.out.print(")"); System.out.println(); } } public class ClassTest { public static void main(String[] args) { try { Class clazz = Class.forName("reflectdemo.SuperHero"); //Printing parametric method ClassUtils.getDeclaredMethod(clazz, "getName", null); //Printing with parameter method ClassUtils.getDeclaredMethod(clazz, "setName", new Class[]{String.class}); } catch (Exception e) { e.printStackTrace(); } } }
The output results are as follows:
Direct Printing public java.lang.String reflectdemo.SuperHero.getName() Manual Construction String getName() Direct Printing public void reflectdemo.SuperHero.setName(java.lang.String) Manual Construction void setName(String)
5.2 getDeclaredMethods()
public class ClassUtils { /** * traversal method * @param clazz */ public static void getDeclaredMethods(Class clazz){ //Method to get all declarations in a class Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods){ System.out.println(method); } } } public class ClassTest { public static void main(String[] args) { try { Class clazz = Class.forName("reflectdemo.SuperHero"); //traversal method ClassUtils.getDeclaredMethods(clazz); } catch (Exception e) { e.printStackTrace(); } } }
The output results are as follows:
public java.lang.String reflectdemo.SuperHero.getName() public java.lang.String reflectdemo.SuperHero.getId() public void reflectdemo.SuperHero.setName(java.lang.String) public void reflectdemo.SuperHero.print() public java.lang.String reflectdemo.SuperHero.getSkill() public void reflectdemo.SuperHero.setAge(java.lang.Integer) public void reflectdemo.SuperHero.setSkill(java.lang.String) public void reflectdemo.SuperHero.setId(java.lang.String) public java.lang.Integer reflectdemo.SuperHero.getAge()
5.3 Method Execution
public class ClassUtils { /** * Execute the set method (via the invoke method of Method) * @param o Entities to be implemented * @param methodName Method name * @param params Method parameter type * @throws Exception */ public static void invokeSetMethod(Object o, String methodName, Class[] params) throws Exception { Method method = o.getClass().getDeclaredMethod(methodName, params); method.invoke(o, "Iron Man"); } /** * Execute the get method (via the invoke method of Method) * @param o Entities to be implemented * @param methodName Method name * @throws Exception */ public static void invokeGetMethod(Object o, String methodName) throws Exception{ Method method = o.getClass().getDeclaredMethod(methodName); Object obj = method.invoke(o); System.out.println(obj); } } public class ClassTest { public static void main(String[] args) { try { Class clazz = Class.forName("reflectdemo.SuperHero"); //Creating Entities Object o = clazz.newInstance(); //Call the set method ClassUtils.invokeSetMethod(o, "setName", new Class[]{String.class}); //Call get method ClassUtils.invokeGetMethod(o, "getName"); } catch (Exception e) { e.printStackTrace(); } } }
The output results are as follows:
Iron Man
The following is an API description of the invoke method
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
Call the underlying method for object representation on method objects with specified parameters.
If the underlying method is static, the specified obj parameter is ignored. It could be null.
If the number of formal parameters required by the underlying method is 0, the length of the args array provided is 0 or empty.
If the underlying method is an instance method, it will be invoked using dynamic method lookup, as described in Section 15.12.4.4 of the second edition of the Java Language Specification; in particular, runtime type coverage based on the target object will occur.
If the underlying method is static, then if the method has not been initialized, the class declaring the method will be initialized.
If the method completes properly, the returned value is returned to the caller; if the value has the original type, it is first properly wrapped in the object. However, if the value has the type of an array of the basic type, the elements of the array are not included in the object; in other words, an array of the original type is returned. If the underlying method return type is void, the call returns null.
-
parameter
obj - Object called from the underlying method
args - parameters for method calls
-
Result
The method represented by this object calls args on obj
-
abnormal
IllegalAccessException - If this method object is enforcing Java language access control and the underlying method is not accessible.
Illegal ArgumentException - If the method is an instance method and the specified object parameter is not an instance of a class or interface declaring the underlying method (or its subclasses or implementers); if the number of actual and formal parameters is different; if the unpacking conversion of the original parameter fails; or if it is possible to expand, pass Through method invocation conversion, the parameter value can not be converted to the corresponding formal parameter type.
Invocation Target Exception - If the underlying method throws an exception.
NullPointerException - If the specified object is empty, the method is an instance method.
ExceptionInInitializerError - If the initialization caused by this method fails.
VI. Summary
In this paper, the definition of reflection, important and commonly used classes and methods in the use of reflection are explained, including Class class, Constructor class, Field class, Method class description and use. Reflection mechanism allows to judge the class of any object at runtime, construct the object of any class, judge the member variables and methods of any class, and call the method of any object. It greatly improves the flexibility and expansibility of the system, but everything has two sides. Reflection destroys the characteristics of Java encapsulation. It is relatively unsafe. It needs to be considered according to the scenario. If there are any mistakes, please criticize and correct them. We hope to make progress together. Thank you.