Reflection: the soul of frame design
The first thing to write is *. java The file is generated by the compiler *.class Finally, the bytecode is run through the virtual machine *.class file
* Framework: semi-finished software. Software development can be carried out on the basis of the framework to simplify coding * Reflection: encapsulating the components of a class into other objects is the reflection mechanism * Benefits: 1. These objects can be run during these operations. 2. It can decouple and improve the scalability of the program
[the external chain image transfer fails, and the source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-Vpffvv22-1620301243675)(D:\java learning video \ javaWeb \ course materials \ day01_ foundation strengthening \ notes \ three stages of Java code. bmp)]
Classloader: loads bytecode files (*. class) into memory
class is used to describe the common characteristics and behavior of all bytecode files
- How to get Class object:
1. Class.forName("Full class name"): Load bytecode file into memory and return Class object //Source code phase * It is mostly used for configuration files, and the class name is defined in the configuration file. Read files and load classes 2. Class name.class: Attribute by class name class obtain //Class object stage * It is used to transfer parameters 3. object.getClass(): getClass()Method in Object Class. //Runtime phase * It is mostly used for obtaining bytecode of objects
example:
package cn.itcast.domain; public class Person { private String name; private int age; public String a; protected String b; String c; private String d; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + ", d='" + d + '\'' + '}'; } public void eat(){ System.out.println("eat..."); } public void eat(String food){ System.out.println("eat..."+food); } }
package cn.itcast.domain; public class Student { public void sleep(){ System.out.println("sleep..."); } }
import cn.itcast.domain.Person; import cn.itcast.domain.Student; public class ReflectDemo1 { /** How to get Class object: 1. Class.forName("Full Class name "): load bytecode file into memory and return Class object 2. Class name Class: obtained through the attribute class of the class name 3. Object getClass(): the getClass() method is defined in the object class. */ public static void main(String[] args) throws Exception { //1.Class.forName("full class name") Class cls1 = Class.forName("cn.itcast.domain.Person"); System.out.println(cls1); //2. Class name class Class cls2 = Person.class; System.out.println(cls2); //3. Object getClass() Person p = new Person(); Class cls3 = p.getClass(); System.out.println(cls3); //==Compare three objects System.out.println(cls1 == cls2);//true System.out.println(cls1 == cls3);//true // Class c = Student.class; System.out.println(c == cls1);//false } }
- Class object function: (must remember)
* Get function: 1. Get member variables * Field[] getFields() : Get all public Decorated member variable * Field getField(String name) Gets the of the specified name public Decorated member variable * Field[] getDeclaredFields() Get all member variables, regardless of modifiers * Field getDeclaredField(String name) 2. Get constructors * Constructor<?>[] getConstructors() * Constructor<T> getConstructor(class<?>... parameterTypes) * Constructor<T> getDeclaredConstructor(class<?>... parameterTypes) * Constructor<?>[] getDeclaredConstructors() 3. How to get members: //Note: the getMethods() method obtains the method of adding its own parent class!!!! // getDeclaredMethods() only gets its own method!!! // There is no question of distinguishing between modifiers * Method[] getMethods() * Method getMethod(String name, class<?>... parameterTypes) * Method[] getDeclaredMethods() * Method getDeclaredMethod(String name, class<?>... parameterTypes) 4. Get full class name * String getName()
(1) Field part:
* Field: Member variable * Operation: 1. Set value * void set(Object obj, Object value) 2. Get value * get(Object obj) 3. Ignore security checks for access modifier * setAccessible(true):Violent reflex
(1) Code of field method:
package cn.itcast.reflect; import cn.itcast.domain.Person; import java.lang.reflect.Field; public class ReflectDemo2 { public static void main(String[] args) throws Exception { //0. Get the Class object of Person Class personClass = Person.class; /* 1. Get member variables * Field[] getFields() * Field getField(String name) * Field[] getDeclaredFields() * Field getDeclaredField(String name) */ //1.Field[] getFields() gets the member variables of all public modifiers Field[] fields = personClass.getFields(); for (Field field : fields) { System.out.println(field); } System.out.println("------------"); //2.Field getField(String name) Field a = personClass.getField("a"); //Gets the value of the member variable a Person p = new Person(); Object value = a.get(p); System.out.println(value); //Set the value of a a.set(p,"Zhang San"); System.out.println(p); System.out.println("==================="); //Field [] getdeclaraedfields(): get all member variables, regardless of modifiers Field[] declaredFields = personClass.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } //Field getDeclaredField(String name) Field d = personClass.getDeclaredField("d"); //Ignore the security check of the access modifier in order to access the value of private member variables d.setAccessible(true);//Violent reflex Object value2 = d.get(p); System.out.println(value2); } }
(2) Constructor part:
* Constructor:Construction method * Create object: * T newInstance(Object... initargs) //Variable parameter * If you use the null parameter construction method to create objects, the operation can be simplified: Class Object newInstance method
(2) Constructor code:
package cn.itcast.reflect; import cn.itcast.domain.Person; import java.lang.reflect.Constructor; import java.lang.reflect.Field; public class ReflectDemo3 { public static void main(String[] args) throws Exception { //0. Get the Class object of Person Class personClass = Person.class; /* 2. Get constructors * Constructor<?>[] getConstructors() * Constructor<T> getConstructor(Class <? > parameterTypes) * Constructor<T> getDeclaredConstructor(Class <? > parameterTypes) * Constructor<?>[] getDeclaredConstructors() */ //Here is only one method: //Constructor < T > getconstructor (class <? >... Parametertypes) //Note: parameters are bytecode objects Constructor constructor = personClass.getConstructor(String.class, int.class); System.out.println(constructor); //create object Object person = constructor.newInstance("Zhang San", 23); System.out.println(person); System.out.println("----------"); //(1) Getting an object without parameters is the same as the following method Constructor constructor1 = personClass.getConstructor(); System.out.println(constructor1); //create object Object person1 = constructor1.newInstance(); System.out.println(person1); //(2) This should be simpler Object o = personClass.newInstance(); System.out.println(o); //constructor1.setAccessible(true); // Same as above } }
(3) Method:
* Method: Method object * Execution method: * Object invoke(Object obj, Object... args) * Get method name: * String getName:Get method name
(3) Method code part:
package cn.itcast.reflect; import cn.itcast.domain.Person; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class ReflectDemo4 { public static void main(String[] args) throws Exception { //0. Get the Class object of Person Class personClass = Person.class; /* 3. How to get members: * Method[] getMethods() * Method getMethod(String name, Class <? > parameterTypes) * Method[] getDeclaredMethods() * Method getDeclaredMethod(String name, Class <? > parameterTypes) */ //Gets the method of the specified name Method eat_method = personClass.getMethod("eat"); Person p = new Person(); //Execution method eat_method.invoke(p); Method eat_method2 = personClass.getMethod("eat", String.class); //Execution method eat_method2.invoke(p,"meal"); System.out.println("-----------------"); //Get the methods of all public modifiers Method[] methods = personClass.getMethods(); for (Method method : methods) { System.out.println(method); String name = method.getName(); System.out.println(name); //method.setAccessible(true); } //Get class name String className = personClass.getName(); System.out.println(className);//cn.itcast.domain.Person } }
Case: (there is something you don't understand) classLoad
- Case:
- Requirements: write a "framework", which can help us create objects of any class and execute any method under the premise of not changing any code of this class
- realization:
- configuration file
- reflex
- Steps:
- Define the full class name of the object to be created and the method to be executed in the configuration file
- Load read configuration file in program
- Use reflection technology to load class files into memory
- create object
- Execution method
- realization:
- Requirements: write a "framework", which can help us create objects of any class and execute any method under the premise of not changing any code of this class
//configuration file //File name: pro properties className=cn.itcast.domain.Student methodName=sleep
It can help us create objects of any class and execute any of its methods:
package cn.itcast.reflect; import cn.itcast.domain.Person; import cn.itcast.domain.Student; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.util.Properties; /** * Framework class */ public class ReflectTest { public static void main(String[] args) throws Exception { //You can create objects of any class and execute any method /* Premise: no code of this class can be changed. You can create objects of any class and execute any method */ /* Person p = new Person(); p.eat();*/ /* Student stu = new Student(); stu.sleep();*/ //1. Load configuration file //1.1 create Properties object Properties pro = new Properties(); //1.2 load the configuration file and convert it into a collection //1.2.1 get the configuration file under the class directory (don't understand!!!) ClassLoader classLoader = ReflectTest.class.getClassLoader(); InputStream is = classLoader.getResourceAsStream("pro.properties"); pro.load(is); //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. Implementation method method.invoke(obj); } }
Notes:
- Concept: describe the of the program. For the computer
- Note: use text to describe the of the program. For programmers
Baidu Encyclopedia:
- Definition: Annotation, also known as metadata. A code level description. It is jdk1 A feature introduced in version 5 and later is at the same level as class, interface and enumeration. It can be declared in front of packages, classes, fields, methods, local variables, method parameters, etc. to describe and annotate these elements.
- Concept description:
- JDK1. New features after 5
- Description of the procedure
- Use annotation: @ annotation name
Annotation function classification: (important)
* Function classification: ①Write document: generate document through the annotation identified in the code [generate document] doc [document] ②Code analysis: analyze the code through the annotation marked in the code [use reflection] //Main learning!!! ③Compilation check: the compiler can realize basic compilation check through the annotations identified in the code[ Override]
1. Explanation: document preparation:
//In the figure below, annodemo1 packge is not written in Java /** * Annotation javadoc demo * * @author itcat * @version 1.0 * @since 1.5 */ public class AnnoDemo1 { /** * Calculate the sum of two numbers * @param a integer * @param b integer * @return Sum of two numbers */ public int add(int a, int b ){ return a + b; } }
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-7ud7gx2w-1620301243683) (C: \ users \ 17274 \ appdata \ roaming \ typora user images \ image-20200817204834039. PNG)]
then:
Click to open:
After:
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-cqiflilw-1620301243686) (C: \ users \ 17274 \ appdata \ roaming \ typora \ typora user images \ image-20200817205141516. PNG)]
3. Explanation: compilation check
=========================================================================
Some predefined annotations in JDK:
- @Override: check whether the method marked by the annotation inherits from the parent class (Interface)
- @Deprecated: the content marked by this annotation indicates that it is outdated
- @SuppressWarnings: suppress warnings
- General transfer parameter all @SuppressWarnings("all")
package cn.itcast.annotation; import java.util.Date; /** * JDK Some predefined annotations in * * @Override : Detect whether the method marked by the annotation inherits from the parent class (Interface) * * @Deprecated: The content marked in this annotation indicates that it is outdated * * @SuppressWarnings: Suppress warning */ @SuppressWarnings("all") public class AnnoDemo2 { @Override public String toString() { return super.toString(); } @Deprecated public void show1(){ //Defective } public void show2(){ //Alternative show1 method } public void demo(){ show1(); Date date = new Date();//There are many outdated methods in it } }
Custom annotation
* format:
Meta annotation public @interface Annotation name{ Attribute list; }
* essence: Annotation is essentially an interface, which inherits the Annotation interface by default
//MyAnno is a custom annotation name public interface MyAnno extends java.lang.annotation.Annotation {}
example:
//Annotation is essentially an interface. What can be defined in the interface and what can be defined in the annotation!!! public @interface MyAnno2 { (public abstract) String show(); }
* attribute: abstract method in the interface / / the interface can be any type, and the annotation can only be the following data types!!!
* requirements:
1. The return value type of the property has the following values: no void
* basic data type
* String
* enumeration
* notes
* arrays of the above types (annotation array, String array, enumeration array, basic data type array)
Example code:
package cn.itcast.annotation; //enumeration public enum Person { P1,P2; }
//annotation public @interface MyAnno2 { }
public @interface MyAnno { String str(); //String int value(); //Basic data type Person per(); //enumeration MyAnno2 anno2(); //annotation String[] strs(); }
2. The attribute is defined, and it needs to be assigned a value when it is used
* if you use the default keyword to initialize the default value of the attribute when defining the attribute, you can not assign the attribute when using annotation.
public @interface MyAnno01{ int value(); String str() default "haha"; }
* if only one attribute needs to be assigned and the name of the attribute is value, value can be omitted and the value can be defined directly.
@MyAnno01(5) public class word{ } //Question: @ webServlet is how to omit?
* when the array is assigned, the value is wrapped with {}. If there is only one value in the array, {} can be omitted
@MyAnno(value=12,per = Person.P1,anno2 = @MyAnno2,strs="bbb") public class Worker { }
//Attribute assignment method: @MyAnno(value=12,per = Person.P1,anno2 = @MyAnno2,strs={"bbb","aaa"}) public class Worker { }
* meta annotation: the annotation used to describe the annotation
1. @Target: describes where the annotation can work
ElementType Value: * TYPE: Can act on classes * METHOD: Can act on Methods * FIELD: Can act on member variables
2. @Retention: describes the stage in which annotations are retained
* @Retention(RetentionPolicy.RUNTIME): The annotation currently described will be retained until class Bytecode file, and JVM Read //Runtime class source three stages!!
3. @Documented: describes whether annotations are extracted into api documents (in the edit document section)
//This meta annotation is added to the a annotation, which annotates the b method. The class of the b method generates an api document, and the a annotation will be displayed on the b method!! //If this meta annotation is not added to the a annotation, the a annotation will not be displayed on the b method!!
4. @Inherited: describes whether annotations are inherited by subclasses
//The subclass here refers to the b annotation annotated by the meta annotation. The b annotation is in class c, and the subclass of class c will also inherit the b annotation!!
//Note: MyAnno3 import java.lang.annotation.*; /** Meta annotation: an annotation used to describe an annotation * @Target: Describe where annotations can work * @Retention: Describes the stage in which annotations are retained * @Documented: Describes whether annotations are extracted into api documents * @Inherited: Describes whether annotations are inherited by subclasses * */ @Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface MyAnno3 { }
//Class: Worker @MyAnno(value=12,per = Person.P1,anno2 = @MyAnno2,strs="bbb") @MyAnno3 public class Worker { @MyAnno3 public String name = "aaa"; @MyAnno3 public void show(){ } }
//The Teacher class inherits the worker class public class Teacher extends Worker { }
=========================================================================
Use (and parse) annotations in the program: get the attribute values defined in the annotations
1. Get the object of the location defined by the annotation (Class, Method,Field)
2. Gets the specified annotation
* getAnnotation(Class)
//In fact, a subclass implementation object of the annotation interface is generated in memory public class ProImpl implements Pro{ public String className(){ return "cn.itcast.annotation.Demo1"; } public String methodName(){ return "show"; } }
3. Call the abstract method in the annotation to obtain the configured property value
example:
//Annotation pro import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Class name and method name required for execution */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Pro { String className(); String methodName(); }
package cn.itcast.annotation; public class Demo1 { public void show(){ System.out.println("demo1...show..."); } }
package cn.itcast.annotation; public class Demo2 { public void show(){ System.out.println("demo2...show..."); } }
package cn.itcast.annotation; import java.io.InputStream; import java.lang.reflect.Method; import java.util.Properties; /** * Framework class */ @Pro(className = "cn.itcast.annotation.Demo1",methodName = "show") public class ReflectTest { public static void main(String[] args) throws Exception { /* Premise: no code of this class can be changed. You can create objects of any class and execute any method */ //1. Analytical notes //1.1 get the bytecode file object of this class Class<ReflectTest> reflectTestClass = ReflectTest.class; //2. Get the annotation object above //In fact, a subclass implementation object of the annotation interface is generated in memory /* public class ProImpl implements Pro{ public String className(){ return "cn.itcast.annotation.Demo1"; } public String methodName(){ return "show"; } } */ Pro an = reflectTestClass.getAnnotation(Pro.class); //3. Call the abstract method defined in the annotation object to obtain the return value String className = an.className(); String methodName = an.methodName(); System.out.println(className); System.out.println(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. Implementation method method.invoke(obj); } }
Case: using annotation, the erasure method will return: the exception occurred, the reason, and the number! (some methods are not understood, and the flow is not clear)
- Class to be checked and wiped!!
//Class to be checked and wiped!! package cn.itcast.annotation.demo; /** * Calculator class defined by Xiao Ming */ public class Calculator { //addition @Check public void add(){ String str = null; str.toString();//Null pointer exception System.out.println("1 + 0 =" + (1 + 0)); } //subtraction @Check public void sub(){ System.out.println("1 - 0 =" + (1 - 0)); } //multiplication @Check public void mul(){ System.out.println("1 * 0 =" + (1 * 0)); } //division @Check public void div(){ System.out.println("1 / 0 =" + (1 / 0)); } public void show(){ System.out.println("Never bug..."); } }
Implemented Code:
//annotation package cn.itcast.annotation.demo; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Check { }
package cn.itcast.annotation.demo; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Simple test framework * * When the main method is executed, it will automatically detect all methods (Methods annotated with Check), judge whether there are exceptions in the method, and record them in the file */ public class TestCheck { public static void main(String[] args) throws IOException { //1. Create calculator object Calculator c = new Calculator(); //2. Get bytecode file object Class cls = c.getClass(); //3. Get all methods Method[] methods = cls.getMethods(); int number = 0;//Number of exceptions BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt")); for (Method method : methods) { //4. Judge whether there is Check annotation on the method if(method.isAnnotationPresent(Check.class)){ //5. Yes, implementation try { method.invoke(c); } catch (Exception e) { //6. Catch exceptions //Record to file number ++; bw.write(method.getName()+ " The method is abnormal"); bw.newLine(); bw.write("Name of exception:" + e.getCause().getClass().getSimpleName()); bw.newLine(); bw.write("Cause of abnormality:"+e.getCause().getMessage()); bw.newLine(); bw.write("--------------------------"); bw.newLine(); } } } bw.write("A total of "+number+" Secondary anomaly"); bw.flush(); bw.close(); } } -------------------------------------------------------------------------------------- e.getCause().getClass().getSimpleName() e.getCause().getMessage()I don't know result: e.getCause() //java.lang.ArithmeticException: / by zero package name + class name + exception reason e.getCause().getMessage() // /by zero exception reason String getSimpleName() Returns the abbreviation of the underlying class given in the source code. e.getCause().getClass().getName() // java.lang.ArithmeticException e.getCause().getClass().getSimpleName() // ArithmeticException
Generate a bug Txt file:
div An exception occurred in the method Name of exception: ArithmeticException Cause of abnormality:/by zero ----------------------------------- One exception occurred in this test
- Case: simple test framework
- Summary:
- Most of the time in the future, we will use annotations instead of custom annotations
- For whom?
- compiler
- For parser
- Annotation is not a part of the program. It can be understood that annotation is a label