Explain Java reflection mechanism in detail
Experience the benefits of reflection through cases
case
- US group take away - > payment - either paid with WeChat or paid by Alipay.
//Interface maker: meituan takeout public interface Mtwm { //Online payment function: void payOnline(); }
public class WeChat implements Mtwm{ @Override public void payOnline() { //Specific functions of wechat payment: System.out.println("I have ordered takeout and am using wechat to pay"); } }
public class AliPay implements Mtwm { @Override public void payOnline() { //Specific Alipay payment: System.out.println("I have ordered takeaway, I am using Alipay to pay for it."); } }
public class BankCard implements Mtwm{ @Override public void payOnline() { System.out.println("I've ordered takeout. I'm paying with China Merchants Bank credit card"); } }
- Test class
public class Test { public static void main(String[] args) { //Define a string to simulate the foreground payment method: String str = "WeChat"; if("WeChat".equals(str)){//str.equals("wechat") ----? Avoid null pointer exceptions //Wechat payment: //new WeChat().payOnline(); pay(new WeChat()); } if("Alipay".equals(str)){ //Alipay payment: //new AliPay().payOnline(); pay(new AliPay()); } if("China Merchants Bank".equals(str)){ pay(new BankCard()); } } //Wechat payment public static void pay(WeChat wc){ wc.payOnline(); } //Alipay payment public static void pay(AliPay ap){ ap.payOnline(); } //Payment by China Merchants Bank public static void pay(BankCard bc){ bc.payOnline(); } }
In order to improve the extensibility of code -- object-oriented characteristics: polymorphism
public class Test { public static void main(String[] args) { //Define a string to simulate the foreground payment method: String str = "WeChat"; if("WeChat".equals(str)){//str.equals("wechat") ----? Avoid null pointer exceptions //Wechat payment: pay(new WeChat()); } if("Alipay".equals(str)){ //Alipay payment: pay(new AliPay()); } if("China Merchants Bank".equals(str)){ pay(new BankCard()); } } //A method parameter is an interface. What is passed in is the object of the implementation class of the interface -- a form of polymorphism public static void pay(Mtwm m){ m.payOnline(); } }
- Polymorphism can indeed improve the scalability of code, but: the scalability is not the best.
- Why not achieve the best: the above branches still need to be deleted or added manually.
- Solution: reflection mechanism
Use reflection to achieve the above functions:
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Demo { public static void main(String[] args) throws Exception { //Define a string to simulate the foreground payment method: String str = "com.zhaoss.test01.AliPay"; //String: actually: it is the fully qualified path of wechat class //The following code uses reflection: Class cls = Class.forName(str);//CLS -- > class specific object -- AliPay bytecode information Object o = cls.newInstance(); Method method = cls.getMethod("payOnline"); method.invoke(o); } }
Re experience reflection through concept
reflex
-
JAVA reflection mechanism is to know all the properties and methods of any class in the running state; For any object,
-
Can call any of its methods and properties; This function of dynamically obtaining information and dynamically calling object methods is called the reflection mechanism of java language.
-
When bytecode files are generated after compilation, the class loader subsystem is responsible for loading class files from the file system through binary byte stream.
-
When executing the program (java.exe), read the bytecode file into the JVM - > this process is called Class loading. Then create a Java. Net in memory Lang. Class object – > this object will be put into the bytecode information. This Class object will load the bytecode information accordingly. This object will be used as an external interface for the program to access various data of this Class in the method area.
-
So: we can see the structure of the class through this object. This object is like a mirror. We can see all kinds of information of the class through the mirror. We vividly call it reflection
-
The ability of the program to examine its self is called introspection. Reflection and introspection are two terms often mentioned together.
Note: during operation, if we want to generate a Class object, the Java virtual machine (JVM) will check whether the Class object of this type has been loaded.
If it is not loaded, the JVM will find it based on the name of the class Class file and load it. Once a class object of a type has been loaded into memory, it can be used to generate all objects of that type.
Supplement:
Dynamic language vs static language
1. Dynamic language
- Is a kind of language whose structure can be changed at run time: for example, new functions, objects, and even code can
When introduced, existing functions can be deleted or other structural changes. Generally speaking, it's transportation
Line time code can change its structure according to certain conditions. - Main dynamic languages: Object-C, c#, JavaScript, PHP, Python, Erlang.
2. Static language
- Corresponding to dynamic language, the language with immutable runtime structure is static language. Such as Java, C, C + +.
- So Java is not a dynamic language, but Java can be called "quasi dynamic language". That is, Java has certain dynamics. We can use reflection mechanism and bytecode operation to obtain characteristics similar to dynamic language.
- The dynamic nature of Java makes programming more flexible!
Class understanding
Create class
//As a parent class public class Person { //attribute private int age; public String name; //method private void eat(){ System.out.println("Person---eat"); } public void sleep(){ System.out.println("Person---sleep"); } }
//Student as a subclass public class Student extends Person { //Properties: private int sno;//Student number double height;//height protected double weight;//weight public double score;//achievement //method: public String showInfo(){ return "I am a three good student"; } private void work(){ System.out.println("I will look for a job in the future-->Become coder programmer ape program yuan"); } //constructor public Student(){ System.out.println("Null parameter constructor"); } private Student(int sno){ this.sno = sno; } Student(int sno,double weight){ this.sno = sno; this.weight = weight; } }
Method for obtaining bytecode
public class Test { public static void main(String[] args) throws ClassNotFoundException { //Case: take the bytecode information of Person as an example //Method 1: get through getClass() method Person p = new Person(); Class c1 = p.getClass(); System.out.println(c1); //Method 2: through the built-in class attribute: Class c2 = Person.class; System.out.println(c2); System.out.println(c1==c2); //Note: mode 1 and mode 2 are not commonly used //Method 3: -- "used most: call the static method forName provided by Class class Class c3 = Class.forName("com.zhaoss.test02.Person"); //Method 4: use class loader (understand skill points) ClassLoader loader = Test.class.getClassLoader(); Class c4 = loader.loadClass("com.zhaoss.test02.Person"); } }
The type that can be used as an instance of Class
Class
(1) Class: external class, internal class
(2) Interface
(3) Annotation
(4) Array
(5) Basic data type
(6)void
verification
public class Demo { public static void main(String[] args) { /* Class Class: (1)Class: external class, internal class (2)Interface (3)annotation (4)array (5)Basic data type (6)void */ Class c1 = Person.class; Class c2 = Comparable.class; Class c3 = Override.class; int[] arr1 = {1,2,3}; Class c4 = arr1.getClass(); int[] arr2 = {5,6,7}; Class c5 = arr2.getClass(); System.out.println(c4==c5);//Result: true The same bytecode is obtained for the same dimension and element type Class c6 = int.class; Class c7 = void.class; } }
Supplement and improve the previous class
//As a parent class public class Person implements Serializable { //attribute private int age; public String name; //method private void eat(){ System.out.println("Person---eat"); } public void sleep(){ System.out.println("Person---sleep"); } }
//Student as a subclass @MyAnnotation(value="hello") public class Student extends Person implements MyInterface{ //Properties: private int sno;//Student number double height;//height protected double weight;//weight public double score;//achievement //method: @MyAnnotation(value="himethod") public String showInfo(){ return "I am a three good student"; } public String showInfo(int a,int b){ return "Overloading methods ====I am a three good student"; } private void work(){ System.out.println("I will look for a job in the future-->Become coder programmer ape program yuan"); } void happy(){ System.out.println("The most important thing in life is to be happy every day"); } protected int getSno(){ return sno; } //constructor public Student(){ System.out.println("Null parameter constructor"); } private Student(int sno){ this.sno = sno; } Student(int sno,double weight){ this.sno = sno; this.weight = weight; } protected Student(int sno,double height,double weight){ this.sno = sno; } @Override @MyAnnotation(value="hellomyMethod") public void myMethod() { System.out.println("I rewritten it myMethod method.."); } @Override public String toString() { return "Student{" + "sno=" + sno + ", height=" + height + ", weight=" + weight + ", score=" + score + '}'; } }
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.LOCAL_VARIABLE; /* @Target:Defines which elements in the program can be modified by the current annotation @Retention:Define the declaration period of the annotation */ @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String value();//attribute }
public interface MyInterface {//Custom interface //Define any abstract method: void myMethod(); }
Get constructor and create object
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Test01 { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //Get bytecode information: Class cls = Student.class; //The constructor can be obtained from bytecode information: //getConstructors can only get the public decorated constructor of the current runtime class Constructor[] c1 = cls.getConstructors(); for(Constructor c:c1){ System.out.println(c); } System.out.println("-------------------"); //Getdeclaraedconstructors: constructor that gets all modifiers of the runtime class Constructor[] c2 = cls.getDeclaredConstructors(); for(Constructor c:c2){ System.out.println(c); } System.out.println("-------------------"); //Gets the specified constructor: //Get empty constructor Constructor con1 = cls.getConstructor(); System.out.println(con1); //A parametric constructor that gets two parameters: Constructor con2 = cls.getConstructor(double.class, double.class); System.out.println(con2); //Get a parameter constructor: and it is private decorated Constructor con3 = cls.getDeclaredConstructor(int.class); System.out.println(con3); //With the constructor, I can create objects: Object o1 = con1.newInstance(); System.out.println(o1); Object o2 = con2.newInstance(180.5, 170.6); System.out.println(o2); } }
Get properties and assign values
import java.lang.reflect.Field; import java.lang.reflect.Modifier; public class Test02 { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException { //Get bytecode information of runtime class: Class cls = Student.class; //Get properties: //getFields: get the public modified attributes in the runtime class and parent class Field[] fields = cls.getFields(); for(Field f:fields){ System.out.println(f); } System.out.println("---------------------"); //Getdeclaraedfields: get all properties in the runtime class Field[] declaredFields = cls.getDeclaredFields(); for(Field f:declaredFields){ System.out.println(f); } System.out.println("---------------------"); //Get the specified property: Field score = cls.getField("score"); System.out.println(score); Field sno = cls.getDeclaredField("sno"); System.out.println(sno); System.out.println("---------------------"); //Specific structure of attribute: //Get modifier /*int modifiers = sno.getModifiers(); System.out.println(modifiers); System.out.println(Modifier.toString(modifiers));*/ System.out.println(Modifier.toString(sno.getModifiers())); //Get the data type of the property: Class clazz = sno.getType(); System.out.println(clazz.getName()); //Get the name of the property: String name = sno.getName(); System.out.println(name); System.out.println("-------------------------------"); //Assign a value to the attribute: (set a value to the attribute, there must be an object) Field sco = cls.getField("score"); Object obj = cls.newInstance(); sco.set(obj,98);//Set a specific value for the score attribute of obj object, which is 98 System.out.println(obj); } }
Get the method and call
import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class Test03 { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { //Get bytecode information: Class cls = Student.class; //Acquisition method: //getMethods: get the methods of the runtime class and all the methods in the parent class (modified by public) Method[] methods = cls.getMethods(); for(Method m:methods){ System.out.println(m); } System.out.println("-----------------------"); //Getdeclaraedmethods: get all methods in the runtime class: Method[] declaredMethods = cls.getDeclaredMethods(); for(Method m:declaredMethods){ System.out.println(m); } System.out.println("-----------------------"); //Get the specified method: Method showInfo1 = cls.getMethod("showInfo"); System.out.println(showInfo1); Method showInfo2 = cls.getMethod("showInfo", int.class, int.class); System.out.println(showInfo2); Method work = cls.getDeclaredMethod("work",int.class); System.out.println(work); System.out.println("-----------------------"); //Specific structure of acquisition method: /* @annotation Modifier return value type method name (parameter list) throws XXXXX {} */ //name: System.out.println(work.getName()); //Modifier: int modifiers = work.getModifiers(); System.out.println(Modifier.toString(modifiers)); //Return value: System.out.println(work.getReturnType()); //Parameter list: Class[] parameterTypes = work.getParameterTypes(); for(Class c:parameterTypes){ System.out.println(c); } //Get comments: Method myMethod = cls.getMethod("myMethod"); Annotation[] annotations = myMethod.getAnnotations(); for(Annotation a:annotations){ System.out.println(a); } //Get exception: Class[] exceptionTypes = myMethod.getExceptionTypes(); for(Class c:exceptionTypes){ System.out.println(c); } //Call method: Object o = cls.newInstance(); myMethod.invoke(o);//Call the mymethod method method of the o object System.out.println(showInfo2.invoke(o,12,45));; } }
Get the package, interface and comments of the class
import java.lang.annotation.Annotation; public class Test04 { public static void main(String[] args) { //Get bytecode information: Class cls = Student.class; //Get the interface of the runtime class: Class[] interfaces = cls.getInterfaces(); for(Class c:interfaces){ System.out.println(c); } //Get the interface of the parent class: //Get the bytecode information of the parent class first: Class superclass = cls.getSuperclass(); //Get interface: Class[] interfaces1 = superclass.getInterfaces(); for(Class c:interfaces1){ System.out.println(c); } //Get the package where the runtime class is located: Package aPackage = cls.getPackage(); System.out.println(aPackage); System.out.println(aPackage.getName()); //Get the annotation of the run class: Annotation[] annotations = cls.getAnnotations(); for(Annotation a:annotations){ System.out.println(a); } } }