<> One , Reflex mechanism

<>1.1 frame

   I'm learning Java On the way , I'm sure you've used all kinds of frameworks . The so-called framework is a semi-finished software , The basic code has been encapsulated and the corresponding API. Software development based on Framework , Can simplify coding . Learning to use a framework does not require understanding reflection , But if you want to write your own framework , So we need to have a deep understanding of the reflection mechanism .

<>1.2 What is reflection mechanism ?

   In program running state , For any class or object , All the properties and methods of this class can be obtained ( Include private properties and methods ), This function of dynamically obtaining information and dynamically calling object methods is called reflection mechanism . In a nutshell , Through reflection , Class is completely transparent to us , You can get anything you want .

<>1.3 Advantages of reflection

* Can be in the process of program running , Manipulate these objects ;
* Decoupled , Improve program scalability .
Before learning reflexes , Let's get to know Java Three phases of code in a computer :

* Source Source code phase :.java Compiled into *.class Bytecode file .
*
Class Class object stage :.class Bytecode file is loaded into memory by classloader , And encapsulate it into Class object ( Used to describe bytecode files in memory ),Class Object to extract the member variables in the original bytecode file and encapsulate them into an array Field[], Extract the constructor from the original bytecode file and encapsulate it into an array Construction[], Encapsulate member methods into arrays Method[]. of course Class There are more than three in the class , There's a lot of encapsulation , We usually use these three .
* RunTime Runtime phase : use new The process of creating objects .

<> Two , obtain Class object

<>2.1 obtain Class Three ways of objects

* 【Source Source code phase 】 Class.forName(“ Holonomic name ”): Load bytecode file into memory , return Class object ;
More for profile , Define the class name in the configuration file , Loading classes by reading configuration files .
* 【Class Class object stage 】 Class name .class: Properties by class name class obtain ;
Mostly used for parameter passing
* 【Runtime Runtime phase 】 object .getClass(): This method is defined in Objec Methods in class , So all classes inherit this method .
How to get bytecode from objects
<>2.2 Method demonstration
public class getClass { public static void main(String[] args) throws Exception
{ // Mode 1 :Class.forName(" Holonomic name "); Class class1 = Class.forName("zzuli.edu.cn.Person"
); //Person Custom entity class System.out.println("class1 = " + class1); // Mode 2 : Class name .class Class
class2 = Person.class; System.out.println("class2 = " + class2);
// Mode 3 : object .getClass(); Person person = new Person(); Class class3 = person.
getClass(); System.out.println("class3 = " + class3); // Compare three objects System.out.
println(class1 == class2); //true System.out.println(class1 == class3); //true }
}
Operation results :

A conclusion can be drawn by comparing the results of the three objects : Same bytecode file (*.class) During a program run , Will only be loaded once , Either way Class All objects are the same .

<> Three , Class Functions of objects

<>3.1 Get features

Here are just some common ones , For details, please refer to jdk Help documentation for .

* Get member variable Field[] getFields() // Get all public Decorated member variable Field getField(String name)
// Gets the public Decorated member variable Field[] getDeclaredFields() // Get all member variables , Do not consider modifiers Field
getDeclaredField(String name) // Get the specified member variable , Do not consider modifiers
* Get construction method Constructor<?>[] getConstructors() // Get all public Decorated constructor Constructor<T>
getConstructor( class <?>... parameterTypes) // Get the specified public Decorated constructor Constructor<?>[]
getDeclaredConstructors() // Get all constructors , Do not consider modifiers Constructor<T>
getDeclaredConstructor( class <?>... parameterTypes) // Gets the specified constructor , Do not consider modifiers
* Get member method Method[] getMethods() // Get all public Decorated member method Method getMethod(String
name, class <?>... parameterTypes) // Gets the public Decorated member method Method[] getDeclaredMethods
() // Get all member methods , Do not consider modifiers Method getDeclaredMethod(String name, class <?>...
parameterTypes) // Gets the member method with the specified name , Do not consider modifiers
* Get full class name String getName()
<>3.2 Field: Member variable

* (1) Set value void set(Object obj, Object value)
* (2) Get value get(Object obj)
* (3) Ignore security check for access modifier setAccessible(true): Violent reflex
<>3.2.1 Tested entity class
import lombok.Getter; import lombok.Setter; import lombok.ToString; @Setter
@Getter @ToString public class Person { public String a; // Maximum range public protected
String b; // Protected type String c; // Default access private String d; // Private type }
<>3.2.2 test getFields and getField(String name) method
/** * Get member variable * * Field[] getFields() * * Field getField(String name) * @throws
Exception */ public class reflectDemo1{ public static void main(String[] args)
throws Exception { // obtain Person Of Class object Class personClass = Person.class;
//1,Field[] getFields() Get all public Decorated member variable Field[] fields = personClass.getFields(
); for(Field field : fields){ System.out.println(field); } System.out.println(
"============================="); //2.Field getField(String name)
Gets the public Decorated member variable Field a = personClass.getField("a"); // Get member variable a Value of
[ Only public , Getting private or nonexistent characters throws an exception ] Person p = new Person(); Object value = a.get(p);
System.out.println("value = " + value);// Because in Person Class a No assignment , So for null // Set member variables a Property value of
a.set(p," Zhang San "); System.out.println(p); } }
Operation results :

<>3.2.3 test getDeclaredFields and getDeclaredField(String name) method
/** * Field[] getDeclaredFields() * Field getDeclaredField(String name) *
@throws Exception */ public class reflectDemo2 { public static void main(String[
] args) throws Exception { // obtain Person Of Class object Class personClass = Person.class;
//Field[] getDeclaredFields(): Get all member variables , Do not consider modifiers Field[] declaredFields =
personClass.getDeclaredFields(); for(Field filed : declaredFields){ System.out.
println(filed); } System.out.println("===================================");
//Field getDeclaredField(String name) // Get the specified member variable , Do not consider modifiers Field d = personClass.
getDeclaredField("d"); //private String d; Person p = new Person(); //Object
value1 = d.get(p);
// If you get it directly, an exception will be thrown , Because for private variables, we can get , But not directly set and get, You must ignore the security check of the access modifier before you can
//System.out.println("value1 = " + value1); // Ignore security check for access modifier , Also known as violent reflex d.
setAccessible(true); Object value2 = d.get(p); System.out.println("value2 = " +
value2); } }
Operation results

be careful : If the access modifier is not ignored, direct access throws an exception as follows

<>3.3 Constructor: Construction method

create object :T newInstance(Object… initargs)
be careful : If you use the null parameter construction method to create an object , Operation can be simplified : Direct use Class Object's newInstance method .

<>3.3.1 Modify the entity class of the test
import lombok.Getter; import lombok.Setter; import lombok.ToString; @Setter
@Getter @ToString public class Person { private String name; private Integer age
; // non-parameter constructor public Person() { } // Constructor for a single parameter , And private constructor private Person(String name){
} // Parametrical constructor public Person(String name, Integer age) { this.name = name; this.age
= age; } }
<>3.3.2 Test how to get the constructor
/** * Get construction method * Constructor<?>[] getConstructors() * Constructor<T>
getConstructor( class <?>... parameterTypes) */ public class reflectDemo3 { public
static void main(String[] args) throws Exception { // obtain Person Of Class object Class
personClass = Person.class; //Constructor<?>[] getConstructors()
// Get all public Decorated constructor Constructor[] constructors = personClass.getConstructors();
for(Constructor constructor : constructors){ System.out.println(constructor); }
System.out.println("=========================================="); // Get parameterless constructor
be careful :Person Class must have a constructor with or without parameters , Otherwise, an exception will be thrown Constructor constructor1 = personClass.
getConstructor(); System.out.println("constructor1 = " + constructor1);
// Create an object using the obtained parameterless constructor Object person1 = constructor1.newInstance(); System.out.
println("person1 = " + person1); System.out.println(
"=========================================="); // Get constructor with parameters //public
Person(String name, Integer age) The order of parameter types should be consistent with that in the constructor , And the parameter type is bytecode file type Constructor
constructor2= personClass.getConstructor(String.class,Integer.class); System.out
.println("constructor2 = " + constructor2); // Create an object using the obtained parameter constructor Object person2 =
constructor2.newInstance("zhangsan", 22); // What we get is a construction method with parameters , You have to specify parameters System.out.
println(person2); System.out.println("========================================="
); // For general parameterless constructors , We don't get the parameterless constructor first and then initialize it , It's a direct call Class In class newInstance() method Object
person3= personClass.newInstance(); System.out.println("person3 = " + person3);
} }
Operation results :

summary : If you use the nonparametric construction method to create an object , Operation can be simplified : Direct use Class Object's newInstance Method creation .

For more than one Declared Two methods of key words , Comparison with two methods without the word , Before 3.2 The same narrative ,getDeclaredConstructor Method can get any access constructor , and getConstructor Method can only get public Decorated constructor , No more testing . In addition, there are also setAccessible(true) method , Set it to true You can do it .

<>3.4 Method: Method object

* Execution method :Object invoke(Object obj, Object… args)
<>3.4.1 Modify the entity class of the test
import lombok.Getter; import lombok.Setter; import lombok.ToString; @Setter
@Getter @ToString public class Person { private String name; private Integer age
; // non-parameter constructor public Person() { } // Parametrical constructor public Person(String name, Integer age)
{ this.name = name; this.age = age; } // Nonparametric method public void eat(){ System.out.
println("eat..."); } // Overloaded parametric method public void eat(String food){ System.out.println(
"eat..."+food); } }
<>3.4.2 Test how to get member methods
/** * Get member method * * Method[] getMethods() * * Method getMethod(String name,
class <?>... parameterTypes) */ public class reflectDemo4 { public static void main(
String[] args) throws Exception { // obtain Person Of Class object Class personClass = Person.
class; // Gets the method of the specified name Method eat_method1 = personClass.getMethod("eat"); // Execution method
Person person= new Person(); Object rtValue = eat_method1.invoke(person);
// If the method has a return value type, you can get , No, it's just null // because eat Method does not return a value , So output null System.out.println("rtValue =
" + rtValue); System.out.println("--------------------------------------------")
; // Get function with parameter , There are two parameters : The first parameter is the method name , The second parameter is the bytecode file that gets the parameter type of the method Method eat_method2 =
personClass.getMethod("eat", String.class); // Execution method eat_method2.invoke(person,
" Apple "); System.out.println("============================================");
// Get method list Method[] methods = personClass.getMethods(); for(Method method :
methods){ // be careful : The way to get it is not just Person Own methods in class System.out.println(method);
// inherit Object The methods in will also be retrieved ( Of course, the premise is public Embellished ) } } }
Operation results

We can see that Person Internal public Methods are printed out , in addition Object In public And the methods were printed out .

Same as before , have Declared Keyword methods these two methods , A way to get any modifier . It also provides setAccessible(true) Methods violent reflex .

in summary : There is no public private in front of reflection , Can be solved by violent reflection .

<>3.5 Get full class name

getName() The class name obtained by the method is the full class name ( With path )
public class getNameDemo { public static void main(String[] args) throws
Exception{ // obtain Person Of Class object Class personClass = Person.class; // Get full class name String
className= personClass.getName(); System.out.println(className); } }
Operation results

<> Four , Application cases of reflection mechanism

<>4.1 case analysis

<>4.1.1 demand

Write a " frame ", Without changing any code of this class , It can help us to create objects of any kind , And execute any of them .

<>4.1.2 realization

(1) configuration file
(2) Reflex mechanism

<>4.1.3 step

(1) Define the full class name of the object to be created and the method to be executed in the configuration file
(2) Load read profile in program
(3) Using reflection technology to load class files into memory
(4) create object
(5) Execution method

<>4.2 code implementation

<>4.2.1 Required entity class

(1)Person class
public class Person { // Nonparametric method public void eat(){ System.out.println("eat..."); }
}
(2)Student class
public class Student { // Nonparametric method public void study(){ System.out.println("I am a
Student"); } }
<>4.2.2 Write profile
className = zzuli.edu.cn.Person methodName = eat
<>4.2.3 Implementation framework
/** * premise : No code of this class can be changed . You can create objects of any kind , Can execute any method * Namely : Reject hard coding */ public class ReflectTest
{ public static void main(String[] args) throws Exception { //1. Load profile
//1.1 establish Properties object Properties pro = new Properties(); //1.2 Load profile
//1.2.1 obtain class Profile in directory ( Use class loader ) ClassLoader classLoader = ReflectTest.class.
getClassLoader(); InputStream inputStream = classLoader.getResourceAsStream(
"pro.properties"); pro.load(inputStream); //2. Get the data defined in the configuration file String className =
pro.getProperty("className"); String methodName = pro.getProperty("methodName");
//3. Load this class into memory Class cls = Class.forName(className); //4. create object Object obj = cls.
newInstance(); //5. Get method object Method method = cls.getMethod(methodName); //6. Execution method
method.invoke(obj); } }
<>4.2.4 Operation results

<>4.2.5 Modify profile , Run again
// Change the information in the configuration file to Student Class and in class study method className = zzuli.edu.cn.Student methodName =
study
Operation results

advantage : For the framework , The basic code has been encapsulated and the corresponding API. Software development based on Framework , Can simplify coding . But if we use the traditional new Form to instantiate , So when the class changes, we have to change it Java code , It's very complicated . modify Java We will recompile the code later , test , Release and other operations . And if we just modify the configuration file , Without modification Java The code is much simpler . In addition, the use of reflection can achieve decoupling effect , If we use new This form is used to instantiate objects . At this time, if one of our instance classes is lost in a small module of the project , Errors will be reported during compilation , Will cause the entire project to fail to start . For reflections, create objects Class.forName(“ Holonomic name ”) This form , All we need at compile time is a string ( Holonomic name ), No error is reported at compile time , In this way, other modules can operate normally , Instead of crashing the whole project due to one module .

If you read this article carefully , Reflection should be mastered , In the next few articles , I will use reflection for hot loading , Decompilation , And use reflection to simply encapsulate a Spring Framework and MyBatis frame . If you want to have a deeper understanding of the reflection mechanism , See the following articles .

Technology
©2019-2020 Toolsou All rights reserved,
Message quality platform series | Full link troubleshooting What is? FPGA? New York Youth Project “ Recapture Wall Street ”: Safeguarding the interests of retail investors Redis Queue implementation java Second kill system , No script , It can be used in production Don't annoy the panda with any cat !「 Kung Fu Panda 」20 It's the year of man 4 blood cartoon | CPU Warfare 40 year , The real king finally appeared !JS How to operate 20 Review strategy for senior students with high marks !!! Big data tells you , How tired are Chinese women MySQL An interview is a must !