The original text is reproduced from http://blog.csdn.net/sinat_38259539/article/details/71799078.
!!!!
Reflection is the soul of frame design
(Prerequisite for use: you must first get the Class of the bytecode represented, which is used to represent the. class file (bytecode))
I. Overview of Reflection
JAVA reflection mechanism is in the running state, for any class, can know all the attributes and methods of this class; for any object, can call any of its methods and attributes; this dynamic acquisition of information and the function of dynamic invocation of the method of the object is called the reflection mechanism of Java language.
To dissect a class, you must first obtain the bytecode file object of that class. Anatomy uses methods in Class classes. So first, we need to get objects of Class type corresponding to each bytecode file.
The above summary is what reflection is.
Reflection is mapping various components of a Java class into one Java object after another.
For example, a class has information such as member variables, methods, construction methods, packages and so on. Using reflection technology, a class can be dissected and its components can be mapped into objects.
(Actually, in a class, there is a class to describe these member methods, construct methods, and add classes)
Figure 1 shows the normal loading process of a class: the principle of reflection is with the class object.
Familiarize yourself with loading: Class objects are designed to read class files into memory and create a Class object for them.
This Class object is very special. Let's look at this Class class first.
2. Look at the API details of Class classes in java (API 1.7)
How to read the api in java? See the basic of Java - String string processing
Instances of Class classes represent classes and interfaces in running Java applications. That is to say, there are more than N instances in jvm, and each class has the Class object. (Including basic data types)
Class has no common constructor. Class objects are automatically constructed by the Java virtual machine when loading classes and by calling the defineClass method in the class loader. That is to say, we don't need to deal with the creation by ourselves. JVM has already created it for us.
Without a common method of construction, there are 64 too many methods. Which of the following will be explained in detail
3. Use of Reflections (demonstrated here with Student class)
Write a Student class first.
1. Three Ways to Get Class Objects
1.1 Object -> getClass();
1.2 Any data type (including basic data types) has a "static" class attribute
1.3 Static methods through Class classes: forName (String className) (commonly used)
1.1 is due to the getClass method in the Object class, because all classes inherit the Object class. So call the Object class to get it
- <span style="font-size:18px;">package fanshe;
- /**
- * Three Ways to Get Class Objects
- * 1 Object -> getClass();
- * 2 Any data type (including basic data types) has a "static" class attribute
- * 3 Static methods through Class classes: forName (String className) (commonly used)
- *
- */
- public class Fanshe {
- public static void main(String[] args) {
- //The first way to get a Class object
- Student stu1 = new Student();//This new produces a Student object, a Class object.
- Class stuClass = stu1.getClass();//Get the Class object
- System.out.println(stuClass.getName());
- //The second way to get Class objects
- Class stuClass2 = Student.class;
- System.out.println(stuClass == stuClass2);//Determine whether the Class object acquired in the first way is the same as the object acquired in the second way?
- //The third way to get Class objects
- try {
- Class stuClass3 = Class.forName("fanshe.Student");//Note that this string must be a real path, that is, the class path with the package name, the package name, the class name
- System.out.println(stuClass3 == stuClass2);//Determine whether the same Class object is acquired in three ways
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- }</span>
Note: During runtime, only one Class object is generated for a class.
Three ways are commonly used in the third way, the first object has to reflect what to do. The second is packages that need to import classes, which rely too heavily on throwing compilation errors without importing packages. Generally, there is a third way, a string can be passed in or written in the configuration file, and many other methods.
2. Obtain the construction method by reflection and use:
Studdent class:
- package fanshe;
- public class Student {
- //Constructing method-------------------------------------------------------------------------------------
- //(Default construction method)
- Student(String str){
- System.out.println("(default)Construction method s = " + str);
- }
- //Parametric-free construction method
- public Student(){
- System.out.println("Called the public, parametric construction method to execute...");
- }
- //A Method of Constructing a Parameter
- public Student(char name){
- System.out.println("Full name:" + name);
- }
- //A Method of Constructing Multiple Parameters
- public Student(String name ,int age){
- System.out.println("Full name:"+name+"Age:"+ age);//There are some problems in the efficiency of implementation, which will be solved later.
- }
- //Protected Construction Method
- protected Student(boolean n){
- System.out.println("Protected Construction Method n = " + n);
- }
- //Private Construction Method
- private Student(int age){
- System.out.println("Private Construction Method Age:"+ age);
- }
- }
There are six construction methods.
Test class:
- package fanshe;
- import java.lang.reflect.Constructor;
- /*
- * Through the Class object, we can get the construction method, member variable and member method of a class, and access members.
- *
- * 1.Get the construction method:
- * 1).Batch method:
- * public Constructor[] getConstructors(): All "public" construction methods
- public Constructor[] getDeclaredConstructors(): Get all constructions (private, protected, default, public)
- * 2).Get a single method and call:
- * public Constructor getConstructor(Class... parameterTypes):Get a single "public" construction method:
- * public Constructor getDeclaredConstructor(Class... parameterTypes):Getting "a constructor" can be private, protected, default, and public;
- *
- * Call the constructor:
- * Constructor-->newInstance(Object... initargs)
- */
- public class Constructors {
- public static void main(String[] args) throws Exception {
- //1. Loading Class Objects
- Class clazz = Class.forName("fanshe.Student");
- //2. Get all public constructions
- System.out.println("**********************All public construction methods*********************************");
- Constructor[] conArray = clazz.getConstructors();
- for(Constructor c : conArray){
- System.out.println(c);
- }
- System.out.println("************All construction methods(Including: Private, Protected, Default, Public)***************");
- conArray = clazz.getDeclaredConstructors();
- for(Constructor c : conArray){
- System.out.println(c);
- }
- System.out.println("*****************A Constructive Approach to Acquiring Public Ownership and No Parameters*******************************");
- Constructor con = clazz.getConstructor(null);
- //1>, because it is a parametric construction method, the type is a null, and it can be written without: what is needed here is a parameter type, remember that it is a type.
- //2>, returns the class object describing the parametric constructor.
- System.out.println("con = " + con);
- //Call the constructor
- Object obj = con.newInstance();
- // System.out.println("obj = " + obj);
- // Student stu = (Student)obj;
- System.out.println("******************Get the private constructor and call it*******************************");
- con = clazz.getDeclaredConstructor(char.class);
- System.out.println(con);
- //Call the constructor
- con.setAccessible(true);//Violent access (ignoring access modifiers)
- obj = con.newInstance('male');
- }
- }
Background output:
- **********************All public construction methods*********************************
- public fanshe.Student(java.lang.String,int)
- public fanshe.Student(char)
- public fanshe.Student()
- ************All construction methods(Including: Private, Protected, Default, Public)***************
- private fanshe.Student(int)
- protected fanshe.Student(boolean)
- public fanshe.Student(java.lang.String,int)
- public fanshe.Student(char)
- public fanshe.Student()
- fanshe.Student(java.lang.String)
- *****************A Constructive Approach to Acquiring Public Ownership and No Parameters*******************************
- con = public fanshe.Student()
- Called the public, parametric construction method to execute...
- ******************Get the private constructor and call it*******************************
- public fanshe.Student(char)
- Name: Male
Call method:
1. Obtain the construction method:
1. Batch method:
public Constructor[] getConstructors(): All "public" construction methods
Public Constructor [] getDeclared Constructors (): Get all constructions (private, protected, default, public)
2) Get a single method and call:
public Constructor getConstructor(Class... parameterTypes): Get a single "public" constructor:
Public Constructor getDeclared Constructor (Class... parameterTypes): Getting "a constructor" can be private, or protected, default, or public;
Call the constructor:
public Constructor[] getConstructors(): All "public" construction methods
Public Constructor [] getDeclared Constructors (): Get all constructions (private, protected, default, public)
2) Get a single method and call:
public Constructor getConstructor(Class... parameterTypes): Get a single "public" constructor:
Public Constructor getDeclared Constructor (Class... parameterTypes): Getting "a constructor" can be private, or protected, default, or public;
Call the constructor:
Constructor-->newInstance(Object... initargs)
The api is interpreted as:
newInstance(Object... initargs)
Create a new instance of the declarative class of the Constructor using the Constructor object representation and initialize the instance with the specified initialization parameters.
Create a new instance of the declarative class of the Constructor using the Constructor object representation and initialize the instance with the specified initialization parameters.
Its return value is of type T, so newInstance is a new instance object that creates a declarative class of constructors. And call for it
3. Get member variables and call them
Studdent class:
- <span style="font-size:14px;">package fanshe.field;
- public class Student {
- public Student(){
- }
- //**************** Field***************************//
- public String name;
- protected int age;
- char sex;
- private String phoneNum;
- @Override
- public String toString() {
- return "Student [name=" + name + ", age=" + age + ", sex=" + sex
- + ", phoneNum=" + phoneNum + "]";
- }
- }</span>
Test class:
- <span style="font-size:14px;">package fanshe.field;
- import java.lang.reflect.Field;
- /*
- * Get member variables and call:
- *
- * 1.Batch
- * 1).Field[] getFields():Get all "public fields"
- * 2).Field[] getDeclaredFields():Get all fields, including: private, protected, default, public;
- * 2.Get a single:
- * 1).public Field getField(String fieldName):Gets a "public" field;
- * 2).public Field getDeclaredField(String fieldName):Get a field (which can be private)
- *
- * Set the value of the field:
- * Field --> public void set(Object obj,Object value):
- * Description of parameters:
- * 1.obj:The object of the field to be set;
- * 2.value:The value to set for the field;
- *
- */
- public class Fields {
- public static void main(String[] args) throws Exception {
- //1. Getting Class Objects
- Class stuClass = Class.forName("fanshe.field.Student");
- //2. Get fields
- System.out.println("************Get all public fields********************");
- Field[] fieldArray = stuClass.getFields();
- for(Field f : fieldArray){
- System.out.println(f);
- }
- System.out.println("************Get all fields(Including private, protected, default)********************");
- fieldArray = stuClass.getDeclaredFields();
- for(Field f : fieldArray){
- System.out.println(f);
- }
- System.out.println("*************Get public fields**And call***********************************");
- Field f = stuClass.getField("name");
- System.out.println(f);
- //Get an object
- Object obj = stuClass.getConstructor().newInstance();//Generate Student Object - "Student stu = new Student();
- //Set values for fields
- f.set(obj, "Lau Andy");//Assign the name attribute in the Student object - "stu.name = Andy Lau"
- //Verification
- Student stu = (Student)obj;
- System.out.println("Verify name:" + stu.name);
- System.out.println("**************Get private fields****And call********************************");
- f = stuClass.getDeclaredField("phoneNum");
- System.out.println(f);
- f.setAccessible(true);//Violent Reflex, Release Private Limitation
- f.set(obj, "18888889999");
- System.out.println("Verification telephone:" + stu);
- }
- }</span><span style="font-size:18px;">
- </span>
Background output:
- ********************** Access to all public fields******************
- public java.lang.String fanshe.field.Student.name
- ******************** Get all fields (including private, protected, default)**************************
- public java.lang.String fanshe.field.Student.name
- protected int fanshe.field.Student.age
- char fanshe.field.Student.sex
- private java.lang.String fanshe.field.Student.phoneNum
- ******************* Gets the public field** and calls the public field*********************************************************************************************
- public java.lang.String fanshe.field.Student.name
- Verify Name: Andy Lau
- ************************** Gets private fields****** and calls********************************
- private java.lang.String fanshe.field.Student.phoneNum
- Verification call: Student [name = Andy Lau, age=0, sex=
Thus it can be seen
When calling a field: you need to pass two parameters:
Object obj = stuClass.getConstructor().newInstance(); // Generate Student Objects - > Student stu = new Student();
// Set values for fields
f.set(obj, "Andy Lau"); // assign a value to the name attribute in the Student object - "stu.name = Andy Lau"
// Set values for fields
f.set(obj, "Andy Lau"); // assign a value to the name attribute in the Student object - "stu.name = Andy Lau"
The first parameter: to pass in the set object, the second parameter: to pass in the argument
4. Get member methods and call them
Studdent class:
- <span style="font-size:14px;">package fanshe.method;
- public class Student {
- //************************ Membership Method***************************//
- public void show1(String s){
- System.out.println("Called: public, String Parametric show1(): s = " + s);
- }
- protected void show2(){
- System.out.println("Called: Protected, parametric show2()");
- }
- void show3(){
- System.out.println("Called: default, no parameters show3()");
- }
- private String show4(int age){
- System.out.println("Called, private, and has a return value, int Parametric show4(): age = " + age);
- return "abcd";
- }
- }
- </span>
Test class:
Console output:
- <span style="font-size:14px;">package fanshe.method;
- import java.lang.reflect.Method;
- /*
- * Get the member method and call:
- *
- * 1.Batch:
- * public Method[] getMethods():Get all "public methods"; (methods that contain parent classes also contain Object classes)
- * public Method[] getDeclaredMethods():Get all member methods, including private (excluding inheritance)
- * 2.Get a single:
- * public Method getMethod(String name,Class<?>... parameterTypes):
- * Parameters:
- * name : Method name;
- * Class ... : Class-TYPE OBJECTS WITH FORMAL PARAMETERS
- * public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
- *
- * Call method:
- * Method --> public Object invoke(Object obj,Object... args):
- * Description of parameters:
- * obj : Objects to call methods;
- * args:The argument passed in the invocation mode;
- ):
- */
- public class MethodClass {
- public static void main(String[] args) throws Exception {
- //1. Getting Class Objects
- Class stuClass = Class.forName("fanshe.method.Student");
- //2. Get all public methods
- System.out.println("***************Getting all the "public" methods*******************");
- stuClass.getMethods();
- Method[] methodArray = stuClass.getMethods();
- for(Method m : methodArray){
- System.out.println(m);
- }
- System.out.println("***************Get all the methods, including private ones*******************");
- methodArray = stuClass.getDeclaredMethods();
- for(Method m : methodArray){
- System.out.println(m);
- }
- System.out.println("***************Acquisition of public ownership show1()Method*******************");
- Method m = stuClass.getMethod("show1", String.class);
- System.out.println(m);
- //Instantiate a Student object
- Object obj = stuClass.getConstructor().newInstance();
- m.invoke(obj, "Lau Andy");
- System.out.println("***************Getting Private show4()Method******************");
- m = stuClass.getDeclaredMethod("show4", int.class);
- System.out.println(m);
- m.setAccessible(true);//Release of Private Limitation
- Object result = m.invoke(obj, 20);//Two parameters are required, one is the object to be invoked (get reflections) and the other is the argument.
- System.out.println("Return value:" + result);
- }
- }
- </span>
- ***************Getting all the "public" methods*******************
- public void fanshe.method.Student.show1(java.lang.String)
- 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 final void java.lang.Object.wait() throws java.lang.InterruptedException
- public boolean java.lang.Object.equals(java.lang.Object)
- public java.lang.String java.lang.Object.toString()
- 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()
- ***************Get all the methods, including private ones*******************
- public void fanshe.method.Student.show1(java.lang.String)
- private java.lang.String fanshe.method.Student.show4(int)
- protected void fanshe.method.Student.show2()
- void fanshe.method.Student.show3()
- ***************Acquisition of public ownership show1()Method*******************
- public void fanshe.method.Student.show1(java.lang.String)
- Called: public, String Parametric show1(): s = Lau Andy
- ***************Getting Private show4()Method******************
- private java.lang.String fanshe.method.Student.show4(int)
- Called, private, and has a return value,intParametric show4(): age = 20
- Return value: abcd
Thus it can be seen:
M = stuClass. getDeclared Method ("show4", int. class); / / / Call Formulation Method (all private) needs to pass in two parameters, the first is the name of the method invoked, the second is the parameter type of the method, remember the type.
System.out.println(m);
m.setAccessible(true); //Release of private definitions
Object result = m.invoke(obj, 20); // Two parameters are required, one is the object to be invoked (retrieved with reflection) and the other is the argument.
System.out.println("return value:" +result);)//
System.out.println(m);
m.setAccessible(true); //Release of private definitions
Object result = m.invoke(obj, 20); // Two parameters are required, one is the object to be invoked (retrieved with reflection) and the other is the argument.
System.out.println("return value:" +result);)//
Console output:
- ***************Getting all the "public" methods*******************
- public void fanshe.method.Student.show1(java.lang.String)
- 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 final void java.lang.Object.wait() throws java.lang.InterruptedException
- public boolean java.lang.Object.equals(java.lang.Object)
- public java.lang.String java.lang.Object.toString()
- 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()
- ***************Get all the methods, including private ones*******************
- public void fanshe.method.Student.show1(java.lang.String)
- private java.lang.String fanshe.method.Student.show4(int)
- protected void fanshe.method.Student.show2()
- void fanshe.method.Student.show3()
- ***************Acquisition of public ownership show1()Method*******************
- public void fanshe.method.Student.show1(java.lang.String)
- Called: public, String Parametric show1(): s = Lau Andy
- ***************Getting Private show4()Method******************
- private java.lang.String fanshe.method.Student.show4(int)
- Called, private, and has a return value,intParametric show4(): age = 20
- Return value: abcd
In fact, the member methods here: there is the word attribute in the model, which is the setter () method and getter() method. There are also fields, which are detailed in the introspection.
5. Reflective main method
Studdent class:
- <span style="font-size:14px;">package fanshe.main;
- public class Student {
- public static void main(String[] args) {
- System.out.println("main The method is executed...");
- }
- }
- </span>
Test class:
- <span style="font-size:14px;">package fanshe.main;
- import java.lang.reflect.Method;
- /**
- * Get the main method of the Student class and don't get confused with the current main method
- */
- public class Main {
- public static void main(String[] args) {
- try {
- //1. Getting bytecode of Student object
- Class clazz = Class.forName("fanshe.main.Student");
- //2. Obtaining main method
- Method methodMain = clazz.getMethod("main", String[].class);//The first parameter is the method name, and the second parameter is the type of the method parameter.
- //3. Call main method
- // methodMain.invoke(null, new String[]{"a","b","c"});
- //The first parameter, the object type, is null because the method is static, and the second parameter is String array. Note that when jdk1.4 is an array, after jdk1.5 is a variable parameter.
- //new String []{a,""b,""c"} is split into three objects when it is disassembled here. So we need to turn it around.
- methodMain.invoke(null, (Object)new String[]{"a","b","c"});//One way
- //methodMain.invoke(null, new Object[]{new String []{a,""b,""c"});//Mode 2
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }</span><span style="font-size:18px;">
- </span>
Console output:
The main method executes...
6. Other uses of reflection methods - running configuration file content by reflection
Studdent class:
- public class Student {
- public void show(){
- System.out.println("is show()");
- }
- }
- className = cn.fanshe.Student
- methodName = show
Test class:
- import java.io.FileNotFoundException;
- import java.io.FileReader;
- import java.io.IOException;
- import java.lang.reflect.Method;
- import java.util.Properties;
- /*
- * Using reflection and configuration files, we can make it possible to update the application without any modifications to the source code.
- * We just need to send the new class to the client and modify the configuration file.
- */
- public class Demo {
- public static void main(String[] args) throws Exception {
- //Getting Class Objects by Reflection
- Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"
- //2 Get show() method
- Method m = stuClass.getMethod(getValue("methodName"));//show
- //3. Call show() method
- m.invoke(stuClass.getConstructor().newInstance());
- }
- //This method receives a key and gets the corresponding value in the configuration file.
- public static String getValue(String key) throws IOException{
- Properties pro = new Properties();//Objects to get configuration files
- FileReader in = new FileReader("pro.txt");//Get the input stream
- pro.load(in);//Loading the stream into the configuration file object
- in.close();
- return pro.getProperty(key);//Returns the value obtained by key
- }
- }
is show()
Demand:
When we upgrade the system, instead of the Student class, we need to write a new Student 2 class, and then we just need to change the file content of pro.txt. The code doesn't need to be changed at all.
When we upgrade the system, instead of the Student class, we need to write a new Student 2 class, and then we just need to change the file content of pro.txt. The code doesn't need to be changed at all.
The student2 class to replace:
- public class Student2 {
- public void show2(){
- System.out.println("is show2()");
- }
- }
Change the configuration file to:
- className = cn.fanshe.Student2
- methodName = show2
Console output:
is show2();
Generics are used at compile time and erased after compilation. So it's possible to pass generic checking by reflection.
Test class:
Console output:
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- /*
- * Override generic checking by reflection
- *
- * For example, if you have a collection of String generics, how can you add an Integer type value to that collection?
- */
- public class Demo {
- public static void main(String[] args) throws Exception{
- ArrayList<String> strList = new ArrayList<>();
- strList.add("aaa");
- strList.add("bbb");
- // strList.add(100);
- //Get the Class es object of ArrayList, invoke the add() method in reverse, and add data
- Class listClass = strList.getClass(); //Get the bytecode object of the strList object
- //Get the add() method
- Method m = listClass.getMethod("add", Object.class);
- //Call the add() method
- m.invoke(strList, 100);
- //Ergodic set
- for(Object obj : strList){
- System.out.println(obj);
- }
- }
- }
Console output:
aaa
bbb
100
bbb
100
// Reflections come to a conclusion. The introspection chapters below are also related to reflection. They can be regarded as advanced use of reflection. If you are interested, you can continue to look at the introspection part of the summary.