1. Reflection
1.1 Overview of reflection
Professional explanation (to learn about it):
- In the running state, for any class, all properties and methods of this class can be known;
- For any object, any of its properties and methods can be called;
- This function of dynamically obtaining information and dynamically calling object methods is called the reflection mechanism of the Java language.
Common understanding: (master)
Objects created using reflection can ignore the contents of the modifier calling class
It can be used in combination with configuration files to write the object information and methods to be created in the configuration file.
- What class is read, create the object of what class
- What method is read, what method is called
- At this time, when the requirements change, there is no need to modify the code, just modify the configuration file.
1.2 What exactly do you learn to learn reflexes?
Reflections are all contents obtained from class bytecode files. (premise)
- How to get object of class bytecode file
- How to get constructors using reflection (create objects)
- How to get member variables using reflection (assign, get value)
- How to get member methods using reflection (run)
1.3 Three ways to obtain bytecode file objects
- The static method forName ("full class name") in the Class class (most commonly used)
- Get it through class attribute
- Get bytecode file object through object
Code example:
//The static method forName in this class//("Full class name of class"): Full class name = Package name + Class nameClass clazz1 = (""); //Source code stage acquisition --- First load the Student into memory, and then obtain the object of the bytecode file//clazz represents the bytecode file object of the Student class.//It is the bytecode file object generated after this file is loaded into memory //2. Get through class attribute//Class name.classClass clazz2 = ; //Because the class file is unique in the hard disk, the object generated after this file is loaded into memory is also unique(clazz1 == clazz2);//true //3. Obtain the bytecode file object through the Student objectStudent s = new Student(); Class clazz3 = (); (clazz1 == clazz2);//true (clazz2 == clazz3);//true
1.4 Bytecode File and Bytecode File Objects
- Java file: It is the java code we wrote ourselves.
- Bytecode file: It is a class file compiled through a java file (it actually exists on the hard disk and can be seen with your eyes)
- Bytecode file object: After the class file is loaded into memory, the virtual machine automatically creates the object.
- This object contains at least: constructor methods, member variables, and member methods.
- And what is our reflection obtaining? Bytecode file object, this object is unique in memory.
1.5 Obtaining the construction method
rule:
- get means obtain
- Declared means private
- The last s means all, plural form
- If the currently obtained private, access permissions must be temporarily modified, otherwise it will not be used
Method name | illustrate |
---|---|
Constructor<?>[] getConstructors() | Obtain all constructs (only public modifications) |
Constructor<?>[] getDeclaredConstructors() | Get all constructs (including private modifications) |
Constructor<T> getConstructor(Class<?>... parameterTypes) | Get the specified construct (only public modification) |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | Get the specified construct (including private modification) |
Code example:
public class ReflectDemo2 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { //1. Obtain the whole (class bytecode file object) Class clazz = (""); //2. Get the constructor object //Get all constructors (public) Constructor[] constructors1 = (); for (Constructor constructor : constructors1) { (constructor); } ("======================="); //Get all constructs (with private ones) Constructor[] constructors2 = (); for (Constructor constructor : constructors2) { (constructor); } ("======================="); //Get the specified empty parameter structure Constructor con1 = (); (con1); Constructor con2 = (,); (con2); ("======================="); //Get the specified construct (all constructs can be obtained, including public and private) Constructor con3 = (); (con3); //Understanding (con3 == con1); //Every time you get the constructor object, a new one will be new. Constructor con4 = (); (con4); } }
1.6 Get the constructor and create an object
Methods involved: newInstance
Code example:
//First of all, there must be a javabean classpublic class Student { private String name; private int age; public Student() { } public Student(String name) { = name; } private Student(String name, int age) { = name; = age; } /** * Get * @return name */ public String getName() { return name; } /** * set up * @param name */ public void setName(String name) { = name; } /** * Get * @return age */ public int getAge() { return age; } /** * set up * @param age */ public void setAge(int age) { = age; } public String toString() { return "Student{name = " + name + ", age = " + age + "}"; } } //Code in the test class://Requirement 1://Get empty parameters and create an object //1. Get the overall bytecode file objectClass clazz = ("."); //2. Construction method for obtaining empty parametersConstructor con = (); //3. Create an object using the empty parameter construction methodStudent stu = (Student) (); (stu); ("============================================="); //Code in the test class://Requirement 2://Get the parameter structure and create an object//1. Get the overall bytecode file objectClass clazz = ("."); //2. Obtain the parameterized construction methodConstructor con = (, ); //3. Temporarily modify the access rights of the constructor (violent reflection)(true); //4. Create an object directlyStudent stu = (Student) ("zhangsan", 23); (stu);
1.7 Get member variables
rule:
- get means obtain
- Declared means private
- The last s means all, plural form
- If the currently obtained private, access permissions must be temporarily modified, otherwise it will not be used
Method name:
Method name | illustrate |
---|---|
Field[] getFields() | Return an array of all member variable objects (only take public) |
Field[] getDeclaredFields() | Return an array of all member variable objects, and you can get it if it exists. |
Field getField(String name) | Return a single member variable object (only public) |
Field getDeclaredField(String name) | Return a single member variable object, and you can get it if it exists |
Code example:
public class ReflectDemo4 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { //Get member variable object //1. Get the class object Class clazz = (""); //2. Obtaining the object (Field object) of member variables can only obtain public modified Field[] fields1 = (); for (Field field : fields1) { (field); } ("==============================="); //Get the object of member variable (public + private) Field[] fields2 = (); for (Field field : fields2) { (field); } ("==============================="); //Get a single member variable object //If the obtained attribute does not exist, an exception will be reported //Field field3 = ("aaa"); //(field3);//NoSuchFieldException Field field4 = ("gender"); (field4); ("==============================="); //Get a single member variable (private) Field field5 = ("name"); (field5); } } public class Student { private String name; private int age; public String gender; public String address; public Student() { } public Student(String name, int age, String address) { = name; = age; = address; } public Student(String name, int age, String gender, String address) { = name; = age; = gender; = address; } /** * Get * @return name */ public String getName() { return name; } /** * set up * @param name */ public void setName(String name) { = name; } /** * Get * @return age */ public int getAge() { return age; } /** * set up * @param age */ public void setAge(int age) { = age; } /** * Get * @return gender */ public String getGender() { return gender; } /** * set up * @param gender */ public void setGender(String gender) { = gender; } /** * Get * @return address */ public String getAddress() { return address; } /** * set up * @param address */ public void setAddress(String address) { = address; } public String toString() { return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}"; } }
1.8 Get member variables and get values and modify values
method | illustrate |
---|---|
void set(Object obj, Object value) | Assignment |
Object get(Object obj) | Get the value |
Code example:
public class ReflectDemo5 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { Student s = new Student("zhangsan",23,"Guangzhou"); Student ss = new Student("lisi",24,"Beijing"); //need: //Use reflection to get member variables and get values and modify values //1. Get the class object Class clazz = (""); //2. Get name member variable //field means the object with the attribute name Field field = ("name"); //Temporarily modify his access rights (true); //3. Set (modify) the value of name //Parameter 1: Indicates which object's name to be modified? //Parameter 2: How much does it mean to be modified? (s,"wangwu"); //3. Get the value of name // means that I want to get the value of the name of this object String result = (String)(s); //4. Print the results (result); (s); (ss); } } public class Student { private String name; private int age; public String gender; public String address; public Student() { } public Student(String name, int age, String address) { = name; = age; = address; } public Student(String name, int age, String gender, String address) { = name; = age; = gender; = address; } /** * Get * @return name */ public String getName() { return name; } /** * set up * @param name */ public void setName(String name) { = name; } /** * Get * @return age */ public int getAge() { return age; } /** * set up * @param age */ public void setAge(int age) { = age; } /** * Get * @return gender */ public String getGender() { return gender; } /** * set up * @param gender */ public void setGender(String gender) { = gender; } /** * Get * @return address */ public String getAddress() { return address; } /** * set up * @param address */ public void setAddress(String address) { = address; } public String toString() { return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}"; } }
1.9 Get member methods
rule:
- get means obtain
- Declared means private
- The last s means all, plural form
- If the currently obtained private, access permissions must be temporarily modified, otherwise it will not be used
Method name | illustrate |
---|---|
Method[] getMethods() | Return an array of all member method objects (only take public) |
Method[] getDeclaredMethods() | Return an array of all member method objects, and you can get it if it exists. |
Method getMethod(String name, Class<?>... parameterTypes) | Return a single member method object (only public) |
Method getDeclaredMethod(String name, Class<?>... parameterTypes) | Return a single member method object, and you can get it if it exists |
Code example:
public class ReflectDemo6 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { //1. Get the class object Class<?> clazz = (""); //2. Obtain method //getMethods can get the method of public modification in the parent class Method[] methods1 = (); for (Method method : methods1) { (method); } ("==========================="); //Get all methods (including private) //But you can only get the methods in your own class Method[] methods2 = (); for (Method method : methods2) { (method); } ("==========================="); //Get the specified method (empty parameter) Method method3 = ("sleep"); (method3); Method method4 = ("eat",); (method4); //Get the specified private method Method method5 = ("playGame"); (method5); } }
1.10 Get the member method and run it
method
- Object invoke(Object obj, Object... args): Run method
- Parameter 1: Call this method with the obj object
- Parameter 2: The passed parameters of the calling method (if there is no, it will not be written)
- Return value: The return value of the method (if not, it will not be written)
Code example:
package .a02reflectdemo1; import ; import ; public class ReflectDemo6 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { //1. Get the bytecode file object Class clazz = ("."); //2. Get an object //This object needs to be used to call the method Student s = new Student(); //3. Get a specified method //Parameter 1: method name //Parameter 2: Parameter list, if not, you can not write Method eatMethod = ("eat",); //run //Parameter 1: represents the method calling object //Parameter 2: The actual parameters required by the method during runtime //Note: If the method has a return value, then you need to receive the result of invoke //If the method does not return value, no reception is required String result = (String) (s, "Chongqing Noodles"); (result); } } public class Student { private String name; private int age; public String gender; public String address; public Student() { } public Student(String name) { = name; } private Student(String name, int age) { = name; = age; } /** * Get * @return name */ public String getName() { return name; } /** * set up * @param name */ public void setName(String name) { = name; } /** * Get * @return age */ public int getAge() { return age; } /** * set up * @param age */ public void setAge(int age) { = age; } public String toString() { return "Student{name = " + name + ", age = " + age + "}"; } private void study(){ ("Students are studying"); } private void sleep(){ ("Students are sleeping"); } public String eat(String something){ ("Students are eating" + something); return "The student has finished eating, very happy"; } }
Interview questions:
Do you think the reflex is good? OK, there are two directions
- The first direction: ignore the modifier to access the content in the class. However, this kind of operation is generally not used in development, it is used at the bottom of the framework.
- The second direction: reflection can be used in combination with configuration files, dynamically create objects and dynamically call methods.
1.11 Practice generic erasure (master concepts and understand code)
Understanding: (Master)
Generics in the collection only exist in the Java file. After compiling into the class file, there are no generics.
Code example: (Learn)
package ; import ; import ; import ; public class ReflectDemo8 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { //1. Create collection object ArrayList<Integer> list = new ArrayList<>(); (123); // ("aaa"); //2. Use reflection to run the add method to add string //Because the reflection uses class bytecode file //Get class object Class clazz = (); //Get add method object Method method = ("add", ); //Operation method (list,"aaa"); //Print the collection (list); } }
1.12 Exercise: Modify the content of a string (master the concept and understand the code)
In this exercise, what I need you to master is the real reason why strings cannot be modified.
String, at the bottom is a byte array of type bytes, called value
private final byte[] value;
Reasons that really cannot be modified: final and private
- Final modification value means that the address value of the value record cannot be modified.
- Private modifies the value and does not provide getvalue and setvalue methods. Therefore, the address value of the value record cannot be obtained or modified in the outside world.
If you want to modify it forcibly, you can use reflection:
Code example: (Learn)
String s = "abc"; String ss = "abc"; // private final byte[] value= {97,98,99}; // There is no method to provide getvalue and setvalue to the outside, and the address value of the value record cannot be modified.// If we use reflection to get the address value.// It can also be modified, the final modified value// The address value of a truly immutable value array can still be modified using reflection, which is more dangerous //1. Get the class objectClass clazz = (); //2. Get the value member variable (private)Field field = ("value"); //But this operation is very dangerous//The higher version of JDK has blocked this operation, and the lower version is still OK//Temporary modification permission(true); //3. Get the address value of the value recordbyte[] bytes = (byte[]) (s); bytes[0] = 100; (s);//dbc (ss);//dbc
1.13 Exercises, reflexes and configuration files combined with dynamic acquisition (key points)
Requirements: Use reflection to create different objects and call methods according to different class names and method names in the file.
analyze:
- ① Load configuration files through Properties
- ②Get class name and method name
- ③Get Class object through class name reflection
- ④Create an object through Class object
- ⑤Get method through Class object
- ⑥ Call method
Code example:
public class ReflectDemo9 { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { //1. Read the configuration file information Properties prop = new Properties(); FileInputStream fis = new FileInputStream("day14-code\\"); (fis); (); (prop); String classname = ("classname") + ""; String methodname = ("methodname") + ""; //2. Get the bytecode file object Class clazz = (classname); //3. Create an object of this class first Constructor con = (); (true); Object o = (); (o); //4. Obtain the method object Method method = (methodname); (true); //5. Operation method (o); } } Information in the configuration file: classname=. methodname=sleep
1.14 Use reflection to save information in objects (key point)
public class MyReflectDemo { public static void main(String[] args) throws IllegalAccessException, IOException { /* For any object, you can save all the field names and values of the object to a file */ Student s = new Student("Little A",23,'female',167.5,"sleep"); Teacher t = new Teacher("Broadcast girl",10000); saveObject(s); } //Save all member variable names and values in the object to the local file public static void saveObject(Object obj) throws IllegalAccessException, IOException { //1. Obtain the object of the bytecode file Class clazz = (); //2. Create IO stream BufferedWriter bw = new BufferedWriter(new FileWriter("myreflect\\")); //3. Get all member variables Field[] fields = (); for (Field field : fields) { (true); //Get the name of the member variable String name = (); //Get the value of the member variable Object value = (obj); //Write out the data (name + "=" + value); (); } (); } } public class Student { private String name; private int age; private char gender; private double height; private String hobby; public Student() { } public Student(String name, int age, char gender, double height, String hobby) { = name; = age; = gender; = height; = hobby; } /** * Get * @return name */ public String getName() { return name; } /** * set up * @param name */ public void setName(String name) { = name; } /** * Get * @return age */ public int getAge() { return age; } /** * set up * @param age */ public void setAge(int age) { = age; } /** * Get * @return gender */ public char getGender() { return gender; } /** * set up * @param gender */ public void setGender(char gender) { = gender; } /** * Get * @return height */ public double getHeight() { return height; } /** * set up * @param height */ public void setHeight(double height) { = height; } /** * Get * @return hobby */ public String getHobby() { return hobby; } /** * set up * @param hobby */ public void setHobby(String hobby) { = hobby; } public String toString() { return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", height = " + height + ", hobby = " + hobby + "}"; } } public class Teacher { private String name; private double salary; public Teacher() { } public Teacher(String name, double salary) { = name; = salary; } /** * Get * @return name */ public String getName() { return name; } /** * set up * @param name */ public void setName(String name) { = name; } /** * Get * @return sales */ public double getSalary() { return salary; } /** * set up * @param sales */ public void setSalary(double salary) { = salary; } public String toString() { return "Teacher{name = " + name + ", salary = " + salary + "}"; } }
2. Dynamic proxy
2.1 Benefits
Non-invasive method enhancement function
2.2 Three elements of dynamic proxy
- 1. The real person to work
- 2. Agent object
- 3. Use proxy to call methods
Remember: the methods that proxy can enhance or intercept are all in the interface, and the interface needs to be written in the second parameter of newProxyInstance.
2.3 Code implementation
public class Test { public static void main(String[] args) { /* need: People outside want big stars to sing a song 1. Get the proxy object Agent object = (the object of the big star); 2. Call the agent's singing method again Agent object. Singing method ("just because you are too beautiful"); */ //1. Get the proxy object BigStar bigStar = new BigStar("Brother Chicken"); Star proxy = (bigStar); //2. Call the singing method String result = ("Just because you are too beautiful"); (result); } } /* * * The function of the class: * Create a proxy * * */ public class ProxyUtil { /* * * Function of the method: * Create an agent for a star object * * Formal parameters: * The celebrity object being represented * * Return value: * Agent created for celebrities * * * * need: * People outside want big stars to sing a song * 1. Get the proxy object * Agent object = (the object of the big star); * 2. Call the agent's singing method again * Agent object. Singing method ("just because you are too beautiful"); * */ public static Star createProxy(BigStar bigStar){ /* Class: Provides a method to generate proxy objects for objects: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) Parameter 1: Used to specify which class loader to load the generated proxy class Parameter 2: Specify interfaces, these interfaces are used to specify what the generated agent is, that is, what methods are there Parameter 3: Used to specify what the generated proxy object should do*/ Star star = (Star) ( (),// Parameter 1: Used to specify which class loader to use to load the generated proxy class new Class[]{},//Parameter 2: Specify interfaces, these interfaces are used to specify what the generated agent will be, that is, what methods are there // Parameter 3: Used to specify what the generated proxy object should do new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* * Parameter 1: Agent object * Parameter 2: Method to run sing * Parameter 3: The actual parameters passed when calling the sing method * */ if("sing".equals(())){ ("Prepare the microphone and collect the money"); }else if("dance".equals(())){ ("Prepare the venue and collect money"); } //Go to find a big star to start singing or dancing //The code expression form: call the method of singing or dancing in the big stars return (bigStar,args); } } ); return star; } } public interface Star { //We can define all methods that want to be proxyed in the interface //Sing public abstract String sing(String name); //Dance public abstract void dance(); } public class BigStar implements Star { private String name; public BigStar() { } public BigStar(String name) { = name; } //Sing @Override public String sing(String name){ ( + "Singing" + name); return "Thanks"; } //Dance @Override public void dance(){ ( + "Dancing"); } /** * Get * @return name */ public String getName() { return name; } /** * set up * @param name */ public void setName(String name) { = name; } public String toString() { return "BigStar{name = " + name + "}"; } }
2.4 Additional extensions
Dynamic proxy, and intercept methods (key point)
for example:
- In this story, the economic man acts as an agent, and if others ask big stars to sing and play basketball, the agent will enhance its functions.
- But if someone asks a big star to clean the toilet, the agent will intercept it and will not call the big star's method.
/* * The function of the class: * Create a proxy * */ public class ProxyUtil { public static Star createProxy(BigStar bigStar){ public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) Star star = (Star) ( (), new Class[]{}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if("cleanWC".equals(())){ ("Intercept, do not call the big star's method"); return null; } //If it is another method, it will be executed normally return (bigStar,args); } } ); return star; } }
2.5 Dynamic Agent Exercises
Enhance the add method, intercept the remove method, and do not intercept other methods or enhance them.
public class MyProxyDemo1 { public static void main(String[] args) { //Dynamic code can be enhanced or intercepted //1. Create a real worker ArrayList<String> list = new ArrayList<>(); //2. Create a proxy object //Parameter 1: Class loader. Current class name.() // Find who it is and load the current class into memory. I will ask him to do something for me to load the subsequent proxy class into memory. //Parameter 2: It is an array, which writes the interface's bytecode file object in the array. // If List is written, it means a proxy. You can proxy all methods in the List interface. These methods can be enhanced or intercepted // However, you must write the interface that is truly implemented by ArrayList // Assuming that in the second parameter, the MyInter interface is written, it is wrong. // Because ArrayList does not implement this interface, it is impossible to enhance or intercept the methods in this interface // Parameter 3: Anonymous internal class used to create proxy objects List proxyList = (List) ( //Parameter 1: Class loader (), //Parameter 2: It is an array that represents the scope of methods that the proxy object can proxy new Class[]{}, //Parameter 3: The essence is the proxy object new InvocationHandler() { @Override //The significance of invoke method parameters //Parameter 1: represents the proxy object, generally not needed (understand) // Parameter 2: It is the method name. We can judge the method name, whether it is enhanced or intercepted //Parameter 3: It is the parameter passed when calling the method in the third step below. //Example 1: //("A Wei is so handsome"); //At this time parameter 2 is the method name of add //At this time, parameter three args[0] is Awei so handsome //Example 2: //(1, "aaa"); //At this time parameter two is the method name set //At this time, parameter three args[0] is 1 args[1]"aaa" public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //Make an enhancement to the add method, the statistics take time if (().equals("add")) { long start = (); //Calling the collection method to truly add data (list, args); long end = (); ("Time-consuming:" + (end - start)); //Return is required, and the return value must be consistent with the actual enhancement or intercepting method. return true; }else if(().equals("remove") && args[0] instanceof Integer){ ("Intercepted method of deletion by index"); return null; }else if(().equals("remove")){ ("Intercepted method of deletion according to object"); return false; }else{ //If the current call is another method, we neither enhance nor intercept (list,args); return null; } } } ); //3. Call method //If the caller is a list, it is like bypassing the second step of the code and adding elements directly //If the caller is a proxy object, this era agent can help us enhance or intercept //Every time a method is called, the collection will not be operated directly // Instead, call the invoke in the proxy first, make judgments in the invoke method, which can enhance or intercept ("aaa"); ("bbb"); ("ccc"); ("ddd"); (0); ("aaa"); //Print the collection (list); } }
Summarize
What is reflection?
- 1. Reflection is a mechanism that obtains the class constructor, attribute, and method by obtaining the class bytecode file object.
- 2. The advantage is that it can help us simplify some operations, such as simplifying configuration files. The disadvantage is that the private attributes we originally set can also be obtained through reflection, which is not safe.
What is a dynamic proxy?
- A non-invasive mechanism for enhancing functions of the method
The three elements of dynamic proxy?
- 1. The real person to work
- 2. Proxy object
- 3. Use proxy to call methods
The proxy object is the same method name as the object that is really working. After using proxy technology, when the original method is called, the object that is really working is no longer called, but the proxy object is called. The underlying layer of the proxy object will splice the object that is really working with its own functions, and then execute it.
The above is personal experience. I hope you can give you a reference and I hope you can support me more.