(ps: This article is applicable to super cute new, so it will say some basic things. Don't spray if you don't like it)
catalogue
There are three common methods for Java reflection foundation code:
Examples of optimizing code through reflection:
All common methods of reflection
Why is it called reflection?
reflect can map variables, methods, etc. in an object into variable objects, method objects, etc. An inappropriate analogy is as like as two peas in a mirror, because the reflection of light causes a mirror image that is exactly the same as that of Object, and the image in the mirror is the object we can manipulate. Object Because we operate the object in the mirror, not the object that originally existed in the mirror, we can let any object look in the mirror, but the way we operate the object in the mirror can remain the same.
There are three common methods for Java reflection foundation code:
// 1. There are two methods to obtain the Class of an object: Class<?> c = Object.class; Class<?> c = new Object().getClass(); // 2. Get the Method of an object [need to throw exception NoSuchMethodException]: Object.getMethod(String: Method name, Class<?>[]: Method parameter list); // 3.invoke the Method of an object // [exception invocationtargetexception and illegalaccessexception need to be thrown]: Method.invoke(Object: object, Object[]: Parameter value);
Let's take an example:
[ Student.java ]
public class Student { private String name; private Integer age; public Student(String name, Integer age) { this.name = name; this.age = age; } 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Careful students can find that the age field is Integer instead of int, because the reflection operation is a class object (Integer is the encapsulated class of int). If you use int type, some strange errors will occur, but it is not that you can't use int, but beginners don't recommend it.
[ Reflect.java ]
import java.lang.reflect.Method; public class Reflect { public static void main(String[] args) { Student s = new Student("Zha Zha Hui", 21); System.out.println(s.toString()); try { Class<?> c = s.getClass(); Method m = c.getMethod("setAge", Integer.class); m.invoke(s, 16); } catch (Exception e) { e.printStackTrace(); } System.out.println(s.toString()); } }
Output:
Student{name='Zha Zha Hui', age=21} Student{name='Zha Zha Hui', age=16}
You can see that the setAge method in Student class has been successfully called.
What's the use of reflection?
Many students will be curious that reflection is so troublesome. Why don't I call the method of the original object directly?
Reflection can optimize a large number of if else statements in the code, making the code more elegant. The most important thing of reflection is that it can be loaded dynamically. At present, almost all popular frameworks on the market (such as Spring and Mybatis) need reflection to complete. Reflection can also realize various operations, which need to be explored by yourself.
Examples of optimizing code through reflection:
[ Action.java ]
public class Actions { public void login(String username, String password){ // Sign in System.out.printf("Sign in: username: %s, password: %s\n", username, password); } public void regist(String username, String password){ // register System.out.printf("register: username: %s, password: %s\n", username, password); } }
[ Reflect.java ]
import java.lang.reflect.Method; public class Reflect { public static void Login(String action, String username, String password){ try{ Method c = Actions.class.getMethod(action, String.class, String.class); c.invoke(new Actions(), username, password); }catch (Exception e){ e.printStackTrace(); } } }
[ Login.java ]
public class Login { public static void main(String[] args) { Reflect.Login("login", "account", "123"); Reflect.Login("regist", "test", "testPass"); } }
Operation results:
Sign in: username: account, password: 123 register: username: test, password: testPass
As can be seen from the above, the amount of code of the main class (Login.java) is greatly reduced, and the operation of login or registration can be realized in one line. Moreover, in the actual development project, we can update it without modifying the source code of the main class, just in action Just update the code in Java. For example, you need to add a function to log off an account, just in action Add public void logoff (String account, String password) {} in Java.
The reflection operation in this example can avoid code bloating and make the code better maintained. However, the disadvantage is that reflection is slower than if else statements. This disadvantage can be ignored in small projects.
All common methods of reflection
// Get Class Class<?> cl = Object.class; // Gets the bytecode file object of the object Class<?> cl2 = Basic data type.class; // Type includes basic data type and reference data type Class<?> cl3 = Class.forName(String: Bytecode full path); // Get a bytecode file through a string. The string must be a full pathname // Operations related to Constructor Object obj = cl.newInstance(); // Parameterless construction object, equivalent to new Object [deprecated] Object obj2 = cl.getDeclaredConstructor().newInstance(); // Same as above [JAVA 1.9 +] Constructor con = cl.getDeclaredConstructor(class<?>[]: Parameter type); // Parametric structure Object obj3 = con.newInstance(Object[]: Parameter content); // Parametric construction instantiation object Constructor[] cons = cl.getConstrutors(); // Get all constructors con.getName(); // Gets the name of the constructor con.getParameterCount(); // Gets the number of parameters of the construction method con.getParameterTypes(); // Gets the parameter type of the constructor // Operations related to Field Field field = cl.getField(String: Attribute name); // Get public property Field field2 = cl.getDeclaredField(String: Attribute name); // Get any attribute Field[] fieldPublic = cl.getFields(); // Get all public properties Field[] fields = cl.getDeclaredFields(); // Get all properties String name = field.getName(); // Get property name Class fieldClass = field.getType() Gets the bytecode file for the attribute type field.setAccessible(Boolean: Mandatory); // When it is true, you can force operations such as modifying the property field.set(Object: object, Object: value); // Set the value of the object's field, which is equivalent to object fieldName = value; Object obj4 = field.get(); // Gets the value of the property // Method related operations Method m = cl.getMethod(String: Method name, Class<?>[]: Method parameter list); // Get public method, getmethod (string methodname, class <? >... Classes) Method m2 = cl.getDeclaredMethod(String: Method name, Class<?>[]: Method parameter list); // Get any method
be careful
In most cases, getDeclaredXXX and getXXX are common, but only getDeclaredXXX can be used when the access modifier of a property or method is protected.
practice
Try to write a reflection tool class, ReflectUtils, to get or set the value of the property in a class containing Getter and Setter methods, and you can call any method in a class.
answer
[ ReflectUtils ]
import java.lang.reflect.Method; public class ReflectUtils { // Reflection call GET public static Object invokeGetter(Object obj, String fieldName){ System.out.println(joinString("get", fieldName)); return invokeMethod(obj, joinString("get", fieldName), null, null); } // Reflection call SET public static void invokeSetter(Object obj, String fieldName, Object value){ invokeMethod(obj, joinString("set", fieldName), new Class<?>[]{value.getClass()}, new Object[]{value}); } /** * Call the method of the object * @param obj object * @param methodName Method name * @param parameterTypes parameter list * @param args parameter * @return Return value of the called method */ public static Object invokeMethod(Object obj, String methodName, Class<?>[] parameterTypes, Object[] args){ try { Class<?> c = obj.getClass(); Method me = c.getDeclaredMethod(methodName, parameterTypes); return me.invoke(obj, args); } catch (Exception e) { e.printStackTrace(); return null; } } /** * Get a standard getter or setter method name * @param prefix Prefix, get / set * @param fieldName Attribute name * @return Prefix + uppercase attribute name */ public static String joinString(String prefix, String fieldName){ char[] chars = fieldName.toCharArray(); chars[0] = chars[0] >= 97 ? (char) (chars[0] - 32) : chars[0]; // a is 97 return prefix + String.valueOf(chars); } }