-
What is reflection?
The Java reflection mechanism allows you to know all the properties and methods of any class in the running state. For any object, you can call any of its methods and properties; This ability to dynamically retrieve information and invoke object methods is called the Reflection mechanism of the Java language.
Reflection can perform all functions of any class at runtime, such as calling methods, modifying the values of member variables, and calling constructors. Reflection can also perform violent reflection even if it is private. Sorry ~ reflection can do whatever it wants.
-
Gets the bytecode Class
To reflect a Class, you must first get the bytecode Class, and there are three ways to get the bytecode
// The first method
Student student = new Student();
Class<? extends Student> studentClass1 = student.getClass();
// The second method
Class<Student> studentClass2 = Student.class;
// The third way
try{ Class<? > studentClass3 = Class.forName("senior.reflection.Student");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Copy the code
-
Gets a member variable of the class
public class Student {
private int age = 18;
private String name = "Zhang";
public String gender = "Male";
}
Copy the code
- GetFields (): Only public qualified member variables can be retrieved
- GetField (String name): Gets a member variable by its name, which can only be public
- GetDeclaredFields (): Retrieves all member variables
- GetDeclaredField (String name): Gets a member variable by its name, any modifier
Student student = new Student();
Class<? extends Student> studentClass = student.getClass();
//getFields()
for (Field field : studentClass.getFields()) {
System.out.println("getFields(): " + field.getName());
}
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
//getDeclaredFields(**)
for (Field field : studentClass.getDeclaredFields()) {
System.out.println("getDeclaredFields(): " + field.getName());
}
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
//getDeclaredField(String name)
Field age1 = studentClass.getDeclaredField("age");
System.out.println("getDeclaredField(String name): "+age1.getName());
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
//getField(String name)
Field age2 = studentClass.getField("age");
System.out.println("getField(String name): " + age2.getName());
Copy the code
Running results:
-
Modifies and gets the value of a member variable
public class Student {
private int age = 18;
private String name = "Zhang";
public String gender = "Male";
}
Copy the code
Private int age = 18
Student student = new Student();
Class<? extends Student> studentClass = student.getClass();
Field age = studentClass.getDeclaredField("age");
// The age before modification
int beforeAge = age.getInt(student);
System.out.println("Age before modification:"+beforeAge);
// Change age to 38
age.setInt(student, 38);
// New age
int afterAge = age.getInt(student);
System.out.println("Age:"+afterAge);
Copy the code
Running results:
Didn’t it say that private can also operate? Why an error…. Don’t panic! It’s a violent reflex!
age.setAccessible(true);
Copy the code
This line of code can reflect private member variables, constructors, normal methods, etc. In essence, reflection does not check permissions, so there is no error when operating on private member variables. This is called “violent reflection”.
Now let’s add the violent reflex and do it again:
Student student = new Student();
Class<? extends Student> studentClass = student.getClass();
Field age = studentClass.getDeclaredField("age");
// Violent reflex
age.setAccessible(true);
// The age before modification
int beforeAge = age.getInt(student);
System.out.println("Age before modification:"+beforeAge);
// Change age to 38
age.setInt(student, 38);
// New age
int afterAge = age.getInt(student);
System.out.println("Age:"+afterAge);
Copy the code
Running results:
-
Gets the constructor of the class
- GetConstructors (): Constructor that can only get public modifications
- getConstructor(Class
… ParameterTypes: a constructor that gets a public modifier from the bytecode of the parameter - GetDeclaredConstructors (): Get all constructors
- getDeclaredConstructor(Class
… ParameterTypes: Gets the constructor from the bytecode of the parameter, any modifier
public class Student {
public Student(a) {
System.out.println("Empty parameter constructor called");
}
// Private methods
private Student(int age, String name) {
System.out.println("The multi-argument private constructor was called:" + age + ""+ name); }}Copy the code
// Get the bytecode Class using the Class nameClass<? > studentClass = Class.forName("senior.reflection.Student");
//getConstructors()
for(Constructor<? > constructor : studentClass.getConstructors()) { System.out.println("getConstructors(): "+constructor);
}
//getConstructor()
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --"); Constructor<? > constructor = studentClass.getConstructor(); Student student = (Student) constructor.newInstance(); System.out.println("getConstructor(): "+constructor);
//getDeclaredConstructors()
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
for(Constructor<? > declaredConstructor : studentClass.getDeclaredConstructors()) { System.out.println("getDeclaredConstructors(): "+declaredConstructor);
}
//getDeclaredConstructor()
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --"); Constructor<? > declaredConstructor = studentClass.getDeclaredConstructor(int.class, String.class);
System.out.println("getDeclaredConstructor(): "+declaredConstructor);
// Violent reflection is used because it is a private constructor
declaredConstructor.setAccessible(true);
// Pass the argument to the constructor to create the object
Student student = (Student) declaredConstructor.newInstance(28."Bill");
Copy the code
Running results:
-
Instantiate an object
Now that the constructor is available, we can instantiate the object through the constructor
-
Instantiate an object with an empty parameter constructor:
public class Student {
public Student(a) {
System.out.println("Empty parameter constructor called"); }}// Get the bytecode Class using the Class nameClass<? > studentClass = Class.forName("senior.reflection.Student"); Constructor<? > constructor = studentClass.getConstructor(); Student student = (Student) constructor.newInstance();Copy the code
-
Instantiate the object with the multi-parameter constructor:
public class Student {
// Private methods
private Student(int age, String name) {
System.out.println("The multi-argument private constructor was called:" + age + ""+ name); }}// Get the bytecode Class using the Class nameClass<? > studentClass = Class.forName("senior.reflection.Student"); Constructor<? > declaredConstructor = studentClass.getDeclaredConstructor(int.class, String.class);
// Violent reflection is used because it is a private constructor
declaredConstructor.setAccessible(true);
// Pass the argument to the constructor to create the object
Student student = (Student) declaredConstructor.newInstance(28."Bill");
Copy the code
-
Gets and calls the member methods of the class
- GetMethods (): Only public qualified member methods can be obtained
- ParameterTypes getMethod(String name, Class[] parameterTypes): public accessorized member method. The first parameter is the method name. The second parameter is the Class bytecode of the parameter type
- GetDeclaredMethods (): Retrieves all member methods
- ParameterTypes getDeclaredMethod(String name, Class[] parameterTypes): getDeclaredMethod(String name, Class[] parameterTypes): getDeclaredMethod(String name, Class[] parameterTypes): Gets all matched member methods
SetAge () and getAge() are public methods setNameAndGender() and getNameAndGender() are private
public class Student {
private int age = 18;
private String name = "Zhang";
public String gender = "Male";
public int getAge(a) {
return age;
}
public void setAge(int age) {
this.age = age;
}
/** * private method */
private String getNameAndGender(a) {
return name;
}
/** * private method */
private void setNameAndGender(String name,String gender) {
this.name = name;
this.gender = gender; }}Copy the code
Reflection gets and calls methods:
// Get the bytecode Class using the Class nameClass<? > studentClass = Class.forName("senior.reflection.Student");
Object student = studentClass.newInstance();
//getMethods()
for (Method method : studentClass.getMethods()) {
System.out.println("getMethods(): "+method.getName());
}
//getDeclaredMethods()
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
for (Method method : studentClass.getDeclaredMethods()) {
System.out.println("getDeclaredMethods(): "+method.getName());
}
//getMethod()
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
Method setAge = studentClass.getMethod("setAge".int.class);
// Invoke manipulates method arguments 1: the object to operate on 2: the parameter to pass in
setAge.invoke(student,48);
Method getAge = studentClass.getMethod("getAge");
// The return value of invoke is the return value of the method
Object age = getAge.invoke(student);
System.out.println("GetMethod () gets the age:"+age);
//getMethod()
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
Method setNameAndGender = studentClass.getDeclaredMethod("setNameAndGender", String.class, String.class);
// Violent reflex
setNameAndGender.setAccessible(true);
// Invoke manipulates method arguments 1: the object to operate on 2: the parameter to pass in
setNameAndGender.invoke(student,"Fifty"."Female");
Copy the code
Running results:
-
conclusion
- The getDeclaredXxx() method retrieves all information but does not contain information about the inherited parent
- The getXxx() method only gets the public modifier information, but it also contains the inherited parent’s public information
- Private information can be manipulated by violent reflection setAccessible(true)
- Instantiate objects using class.newinstance ()
-
How to store strings in an ArrayList?
Now that we’re done with reflection, it should be pretty easy
- Get the add method of the list by reflection
- Pass arguments to the Add method via invoke
- Print the data for the list
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Create an array of type Integer
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
// Get the add method of the list by reflection
Method add = list.getClass().getMethod("add", Object.class);
// Use invoke to pass parameters to a method
add.invoke(list,"I'm a string");
for(Object item : list) { System.out.println(item); }}Copy the code
Running results: