Introduction to reflection
Reflection is an important advanced feature in java and is used in many frameworks. Dynamic proxies are also implemented using reflection.
Reflection allows us to get all the information about a class or object while the program is running. For a class, reflection obtains all its attributes and method information. For an object, we can call all its methods and attributes and understand that reflection is the anatomy of a class.
Four Core Classes of Reflection
1.Class Class
Class class in JDK's java. Under the Lang package, it is the entry for reflection. In java, each class has a corresponding Class object. This Class object is used to represent information about this class and is stored in our javac compiled ** byte code file (.class)**. When we want a new object of this class, the class loader of the JVM loads the corresponding Class object into the JVM (the Class object is stored in the heap, which is the loading of the class). The JVM then creates the instance objects we want based on the information of this Class object.
That is, if we want to know all the information about this class, we need to get this Class object. Class objects are also instance objects of Class classes, so Class classes are the entry for reflection, and only if you get this Class object can you do the next operation. However, Class classes only have private constructors, and we cannot instantiate them directly through the new operator. The corresponding Class object can only be created and loaded by the JVM. Once we have this Class object, we can call the methods in the Class class to get the specified information.
Three ways to get a Class object
// 1. Literal Constants for Class Objects Class stu = students.class; /*2. Obtain Class objects by their path names, which is how reflection obtains Class objects Class.forName()A ClassNotFoundException needs to be captured because the compiler cannot detect the passing string Does the corresponding class exist */ Class stu1 = Class.forName("com.reflect.students"); //3. Call the object's getclass method (inherited from the Object class), which requires a new object first students stu2 = new students(); Class stuclass = stu2.getClass(); //All three methods get the same object because each class in the JVM has a corresponding Class object and only one corresponding Class object
Get Constructor
Constructor<?>[] | getConstructors() | Get all public constructors for this class |
---|---|---|
Constructor<?>[] | getDeclaredConstructors() | Gets all constructors for this class |
Constructor | getDeclaredConstructor(Class<?>... parameterTypes) | Gets any constructor specified by a single class |
Constructor | getConstructor(Class<?>... parameterTypes) | Gets a single public constructor specified by the class |
public class students extends person{ public String name; private String id; public int age; static int score; public students() { } public students(String name, String id, int age) { this.name = name; this.id = id; this.age = age; } private students(int age) { this.age = age; } private students(String name, String id) { this.name = name; this.id = id; } }
@Test public void reflect_getConstructor() throws NoSuchMethodException, ClassNotFoundException { Class stu = Class.forName("com.reflect.students"); // Constructor<?> [] getConstructors () Gets the constructors for all public s for (Constructor con:stu.getConstructors()) { System.out.println(con); } System.out.println("------------"); //Constructor<?> [] getDeclaredConstructors () Gets all constructors for (Constructor con:stu.getDeclaredConstructors()) { System.out.println(con); } System.out.println("------------"); // Constructor <T> getDeclaredConstructor (Class <?>... parameterTypes) Gets a single specified constructor System.out.println(stu.getDeclaredConstructor(int.class)); System.out.println("------------"); //Constructor<T> getConstructor (Class<?>... parameterTypes) Gets the constructor for a single specified public System.out.println(stu.getConstructor(String.class,String.class,int.class)); }
//------->Output public com.reflect.students(java.lang.String,java.lang.String,int) public com.reflect.students() ------------ private com.reflect.students(java.lang.String,java.lang.String) private com.reflect.students(int) public com.reflect.students(java.lang.String,java.lang.String,int) public com.reflect.students() ------------ private com.reflect.students(int) ------------ public com.reflect.students(java.lang.String,java.lang.String,int)
Get Fields
Field[] | getFields() | Gets the public fields for all this class and all its superclasses |
---|---|---|
Field | getField(String name) | Gets a single specified public field for this class |
Field | getDeclaredField(String name) | Gets a single specified field of this class, which can be private |
Field[] | getDeclaredFields() | Get all fields of this class |
public class person { public String name; private String id; } ------------------------------------------------------------------------ public class students extends person{ public String name; private String id; public int age; static int score; }
@Test public void reflect_getFieldNames() throws ClassNotFoundException, NoSuchFieldException { Class stu = Class.forName("com.reflect.students"); // Field[] getFields() for (Field f:stu.getFields()) { System.out.println(f); } System.out.println("------------"); // Field getField(String name) System.out.println(stu.getField("age")); System.out.println("------------"); // Field[] getDeclaredFields() for (Field f:stu.getDeclaredFields()) { System.out.println(f); } System.out.println("------------"); System.out.println(stu.getDeclaredField("id")); }
//------->Output public java.lang.String com.reflect.students.name public int com.reflect.students.age //The public name field of the parent class is also returned public java.lang.String com.reflect.person.name ------------ public java.lang.String com.reflect.students.name ------------ public java.lang.String com.reflect.students.name private static java.lang.String com.reflect.students.id public int com.reflect.students.age static int com.reflect.students.score ------------ private static java.lang.String com.reflect.students.id
Getting Method
Method[] | getMethods() | Get the public method for this class and all its superclasses |
---|---|---|
Method | getMethod(String name, Class<?>... parameterTypes) | Gets the public method specified by the class |
Method[] | getDeclaredMethods() | Get all methods of this class |
Method | getDeclaredMethod(String name, Class<?>... parameterTypes) | Gets any method specified by the class |
public class person { public String name; private String id; public person() { } private person(String name) { this.name = name; } private String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } } ----------------------------------------------------------------------------- public class students extends person{ public String name; private String id; public int age; static int score; public students() { } public students(String name, String id, int age) { this.name = name; this.id = id; this.age = age; } private students(int age) { this.age = age; } private students(String name, String id) { this.name = name; this.id = id; } public String getName() { return name; } public String getId() { return id; } public int getAge() { return age; } @Override public String toString() { return "students{" + "name='" + name + '\'' + ", id='" + id + '\'' + ", age=" + age + '}'; } private void ac(){ } }
@Test public void reflect_getMethod() throws ClassNotFoundException, NoSuchMethodException { Class stu = Class.forName("com.reflect.students"); // Method[] getMethods() Gets all public methods for (Method f:stu.getMethods()) { System.out.println(f); } System.out.println("------------"); //Method getMethod (String name, Class<?>... parameterTypes) Gets a single specified public method System.out.println(stu.getMethod("getName")); System.out.println("------------"); // Method[] getDeclaredMethods() Gets all methods for (Method f:stu.getDeclaredMethods() ) { System.out.println(f); } System.out.println("------------"); // Method getDeclaredMethod (String name, Class<?>... parameterTypes) Gets a single specified method System.out.println(stu.getDeclaredMethod("ac")); }
//------->Output public java.lang.String com.reflect.students.toString() public java.lang.String com.reflect.students.getName() public java.lang.String com.reflect.students.getId() public int com.reflect.students.getAge() //Parent person public void com.reflect.person.setName(java.lang.String) public void com.reflect.person.setId(java.lang.String) //object class public final void java.lang.Object.wait() throws java.lang.InterruptedException 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 boolean java.lang.Object.equals(java.lang.Object) 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() ------------ public java.lang.String com.reflect.students.getName() ------------ public java.lang.String com.reflect.students.toString() public java.lang.String com.reflect.students.getName() public java.lang.String com.reflect.students.getId() private void com.reflect.students.ac() public int com.reflect.students.getAge() ------------ private void com.reflect.students.ac()
2.Constructot class
Create instance objects through the newInstance method in the Constructot class
@Test public void getnewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class<?> stu = Class.forName("com.reflect.students"); // Gets all constructors, and each constructor is a Constructor object Constructor[] constructors = stu.getConstructors(); Constructor<?> declaredConstructor = stu.getDeclaredConstructor(); System.out.println(constructors[0].getClass().getName()); /* Get an instance of the parameterless constructor at jdk1.9 was discarded Instead, getDeclaredConstructor().newInstance(), Get the corresponding constructor object and create an instance, then get the parameterless constructor without parameters Every creation has a new instance object */ students o = (students) stu.newInstance(); students o1 = (students) stu.getDeclaredConstructor().newInstance(); System.out.println(o == o1);//false }
Constructot class can also get the constructor's parameter type, number of parameters, annotations, modifiers and so on, which are not described here, mainly the instantiation of the object
3.Field class
Assigning values to fields
@Test public void getfield() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException { Class<?> stu = Class.forName("com.reflect.students"); //Create instance objects from parameterless constructors students o = (students) stu.getDeclaredConstructor().newInstance(); //Get the name field Field field1 = stu.getField("name"); System.out.println( " " + field1); //Call set assignment field1.set(o,"ss"); Object o1 = field1.get(o); String name = o.getName(); System.out.println(o1 + " " + name); }
4.Method Class
Call Method
@Test public void getMethod() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { Class<?> stu = Class.forName("com.reflect.students"); students o = (students) stu.getDeclaredConstructor().newInstance(); Method setAge = stu.getMethod("setAge", int.class); //Call invoke to run setAge method, passing in object and specified parameter setAge.invoke(o,10); System.out.println(o.getAge()); }
There are also a series of methods in the Method class to get method modifiers, parameters, return types, and so on.
setAccessible
For private or default decorated methods and member variables, the calling method and the value of the query variable cannot be modified by default
Access by modifying permissions through setAccessible
@Test public void setA() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException, InstantiationException, IllegalAccessException { Class<?> stu = Class.forName("com.reflect.students"); students o = (students) stu.getDeclaredConstructor().newInstance(); Field id = stu.getDeclaredField("id"); id.setAccessible(true); id.set(o,"sss"); System.out.println(id.get(o)); }
Method is used the same way