Java annotation and reflection
annotation
java.Annotation
Introduction to annotation
- Annotation is from jdk1 5 new technologies introduced
- Function of Annotation:
- Not the program itself, you can explain the program (this is no different from comments)
- It can be read by other programs (such as compiler, etc.)
- Format of Annotation:
- Annotations exist in the code as "@ annotation name". You can also add some parameter values, such as @ SuppressWarnings(value = "unchecked")
- Where is Annotation used?
- It can be attached to package, class, method, field, etc., which is equivalent to adding additional auxiliary information to them. We can access these metadata through reflection mechanism programming
Built in annotation
- @Override: defined in Java In lang. override, this annotation is only applicable to rhetoric, indicating that one method declaration intends to override another method declaration in the superclass
- @Deprecated: defined in Java In lang. deprecated, this annotation can be used for rhetoric, attributes, and classes, indicating that programmers are not encouraged to use such elements, usually because it is dangerous or there are better choices
- @SuppressWarnings: defined in Java Lang. SuppressWarnings, used to suppress warnings at compile time
- Different from the previous two annotations, you need to add a parameter to use it correctly. These parameters have been defined. We can use them selectively
- @SuppressWarnings("all")
- @SuppressWarnings("unchecked")
- @SuppressWarnings("unchecked","deprecation")
- Wait
Example
package annotation; import java.util.ArrayList; import java.util.List; /** * When is the annotation */ @SuppressWarnings("all") public class Test01 extends Object{ @Override//Rewritten annotation public String toString() { return super.toString(); } @Deprecated//It is not recommended for programmers, but it can be used, or there is a better way public static void test(){ System.out.println("Deprecated"); } public void test02(){ List list = new ArrayList(); } public static void main(String[] args) { test(); } }
Custom annotation, meta annotation
Meta annotation
- The function of meta annotation is to annotate other annotations. java defines four standard meta annotation types, which are used to provide descriptions of other annotation types.
- These types and the classes they support are in Java You can find it in the lang.annotation package
- (@Target,@Retention,@Documented,@Inherited)
- @Target: used to describe the scope of use of annotations (i.e. where the described annotations can be used)
- @Retention: indicates the level at which the annotation information needs to be saved. It is used to describe the annotation life cycle [source < class < runtime]
- @Documented: indicates that the annotation will be included in the javadoc
- @Inherited: indicates that the subclass can inherit the annotation in the parent class
Example:
package annotation; import java.lang.annotation.*; /** * Test meta annotation */ public class Test02 { @MyAnnotation public void test(){ } } //Define an annotation //@Target indicates where our annotation can be used @Target(value = {ElementType.METHOD,ElementType.TYPE}) //@Retention indicates where our annotation is still valid // runtime>class>source @Retention(RetentionPolicy.RUNTIME) //@Documented indicates whether our annotations are generated in JAVA doc @Documented //@The Inherited subclass can inherit the annotation of the parent class!! @Inherited @interface MyAnnotation{ }
Custom annotation
- When using @ interface to customize annotations, automatically inherit Java lang.annotation. Annotation interface
- analysis:
- @Interface is used to declare an annotation. Format: public @interface annotation name {definition content}
- Each of these methods actually declares a configuration parameter
- The name of the method is the name of the parameter
- The return value type is the type of the parameter (the return value can only be the basic type: Class String enum)
- You can declare the default value of the parameter through default
- If there is only one parameter member, the general parameter name is value (if it is value, it can be omitted when annotation is written to the configuration)
- An annotation element must have a value. When defining an annotation element, we often use an empty string with 0 as the default value
Example:
package annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Custom annotation */ public class Test03 { //The annotation can display the assignment. If there is no default value, we must assign it @MyAnnotation2(name = "Cool",schools ={"Earth University"}) public void test(){ } @MyAnnotation3("Cool") public void test2(){ } } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2{ //Annotated parameters: parameter type + parameter name () String name() default ""; int age() default 0; int id() default -1;//If the default value is - 1, it means that it does not exist [indexof returns - 1 if it is not found] String[] schools() default {"Tsinghua University"}; } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation3{ String value(); }
Reflection mechanism
java.Reflection - > Dynamic
Overview of Java reflection mechanism
Static VS dynamic language
Dynamic language
- It is a kind of language that can change its structure at run time: for example, new functions, objects and even code can be introduced, existing functions can be deleted or other structural changes. Generally speaking, the code can change its structure according to some conditions at run time.
- Main dynamic languages: Object-C, c#, JavaScript, PHP, Python, etc
Static language
- Corresponding to dynamic language, the language whose runtime structure cannot be changed is static language. Such as Iava, C, C++
- Java is not a dynamic language, but Java can be called a "quasi dynamic language". That is, Java has certain dynamics. We can use reflection mechanism to obtain characteristics similar to dynamic language. The dynamic nature of Java makes programming more flexible!
Java Reflection
- Reflection
Is the key to Java being regarded as a dynamic language. Reflection mechanism allows programs to obtain the internal information of any class with the help of reflection API during execution, and can directly operate the internal properties and methods of any object.
Class c = Class.forName("java.lang.String")
- After loading the Class, a Class object is generated in the method area of heap memory (a Class has only one Class object), which contains the complete Class structure information. We can see the structure of the Class through this object. This object is like a mirror, through which we can see the structure of the Class. Therefore, we vividly call it reflection
Normal method: import the required "package class" name ----- "and obtain the instantiated object through new instantiation -----"
Reflection method: instantiate the object -- "getClass() method --" to get the complete "package class" name
- Functions provided by Java reflection mechanism
- Determine the class of any object at run time
- Construct an object of any class at run time
- Judge the member variables and methods of any class at run time
- Get generic information at run time
- Call the member variables and methods of any object at run time
- Processing annotations at run time
- Generate dynamic proxy
- ...
Advantages and disadvantages of Java reflection
advantage
- It can dynamically create objects and compile, reflecting great flexibility
shortcoming
- It has an impact on performance. Using reflection is basically an interpretation operation. We can tell the JVM what we want to do and it meets our requirements. Such operations are always slower than performing the same operation directly
Main API s related to reflection
- java.lang.Class: represents a class
- java.lang.reflect.Method: represents the method of the class
- java.lang.reflect.Field: represents the member variable of the class
- java.lang.reflect.Constructor: represents the constructor of the class
- ...
Example:
package reflection; /** * What is reflection */ public class Test01 { public static void main(String[] args) throws ClassNotFoundException { //Gets the Class object of the Class through reflection Class c1 = Class.forName("reflection.User"); System.out.println(c1); Class c2 = Class.forName("reflection.User"); Class c3 = Class.forName("reflection.User"); Class c4 = Class.forName("reflection.User"); //A Class has only one Class object in memory // After a Class is loaded, the whole structure of the Class will be encapsulated in the Class object System.out.println(c2.hashCode());//If the hashCode is the same, it represents the same class System.out.println(c3.hashCode()); System.out.println(c4.hashCode()); } } //Entity class POJO entity class User{ private String name; private int id; private int age; public User(){ } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public User(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", id=" + id + ", age=" + age + '}'; } }
result:
class reflection.User
460141958
460141958
460141958
Understand Class class and get Class instance
Class class
- The following methods are defined in the Object class, which will be inherited by all subclasses
public final Class getClass();
- The type of the return value of the above method is a Class class, which is the source of Java reflection. In fact, the so-called reflection is also well understood from the running results of the program, that is, the name of the Class can be obtained through object reflection.
The information that can be obtained after the object looks in the mirror: the properties, methods and constructors of a Class, and which interfaces a Class implements. For each Class, the JRE(java runtime environment) keeps a constant Class type object for it. A Class object contains information about a specific structure (class/interface/enum/annotation/primitive type/void / []).
- Class itself is also a class
- Class objects can only have system created objects
- A loaded Class has only one Class instance in the JVM
- A class object corresponds to a class loaded into the JVM Class file
- Each Class instance will remember which Class instance it was generated from
- All loaded structures in a Class can be completely obtained through Class
- Class is the root of Reflection. For any class you want to dynamically load and run, you have to obtain the corresponding class object first
Common methods of Class
Get an instance of Class
- If a specific class is known, it is obtained through the class attribute of the class. This method is the most safe and reliable, and the program performance is the highest
Class clazz = Person.class;
- Given an instance of a Class, call the getClass() method of the instance to obtain the Class object
Class clazz = person.getClass();
- If the full Class name of a Class is known and the Class is under the Class path, it can be obtained through the static method forName() of Class class, and ClassNotFoundException may be thrown
Class clazz = Class.forName("demo01.Student");
- The built - in basic data type can use the class name directly Type
- You can also use ClassLoader, which we will explain later
Example:
package reflection; /** * What are the creation methods of test Class */ public class Test03 { public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); System.out.println("This person is:"+person.name); //Method 1: obtained by object Class c1 = person.getClass(); System.out.println(c1.hashCode()); //Method 2: forName (package name) Class c2 = Class.forName("reflection.Student"); System.out.println(c2.hashCode()); //Method 3: pass the class name Class get Class c3 = Student.class; System.out.println(c3.hashCode()); //Method 4: wrapper classes of basic built-in types have a Type attribute Class c4 = Integer.TYPE; System.out.println(c4 +"----"+c4.hashCode()); //Get parent class Class c5 = c1.getSuperclass(); System.out.println(c5); } } class Person{ public String name; public Person(){ } public Person(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } class Student extends Person{ public Student(){ this.name = "student"; } } class Teacher extends Person{ public Teacher(){ this.name = "teacher"; } }
result:
This person is: student
460141958
460141958
460141958
int----1163157884
class reflection.Person
What types can have Class objects?
- Class: external class, member (member internal class, static internal class), local internal class, anonymous internal class
- interface: interface
- []: array
- enum: Enumeration
- Annotation: annotation @ interface
- primitive type: basic data type
- void
Example:
package reflection; import java.lang.annotation.ElementType; /** * Class objects of all types */ public class Test04 { public static void main(String[] args) { Class c1 =Object.class;//class Class c2 =Comparable.class;//Interface Class c3 =String[].class;//One dimensional array Class c4 =int[][].class;//Two dimensional array Class c5 =Override.class;//annotation Class c6 = ElementType.class;//enumeration Class c7 = Integer.class;//Basic data type Class c8 = void.class;//void Class c9 = Class.class;//Class System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c4); System.out.println(c5); System.out.println(c6); System.out.println(c7); System.out.println(c8); System.out.println(c9); /** * As long as the element type is the same as the dimension, it is the same Class */ int[] a = new int[10]; int[] b = new int[100];//Two arrays with different lengths have the same Class as long as they have the same type System.out.println(a.getClass().hashCode()); System.out.println(b.getClass().hashCode()); } }
result:
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
460141958
460141958
Java Memory Analysis
Class loading and ClassLoader
Understanding: class loading process
When a program actively uses a class, if the class has not been loaded into memory, the system will initialize the class through the following three steps.
(Load)------------->(Link)---------------->(Initialize)
Class loading and ClassLoader understanding
- Load: load the bytecode content of the class file into memory, convert these static data into the runtime data structure of the method area, and then generate a Java. Net file representing this class Lang.class object
- Link: the process of merging the binary code of the Java class into the running state of the JVM:
- Verification: ensure that the loaded class information complies with the JVM specification and there are no security problems
- Preparation: the stage of formally allocating memory for class variables (static) and setting the default initial value of class variables. These memory will be allocated in the method area.
- Resolution: the process of replacing the symbolic reference (constant name) in the virtual machine constant pool with a direct reference (address)
- initialization:
- The process of executing a class constructor () method. The class constructor () method is generated by the combination of the assignment actions of all class variables in the class automatically collected by the compiler and the statements in the static code block. (the class constructor is used to construct class information, not the constructor to construct the class object)
[class is the template of object] - When initializing a class, if it is found that its parent class has not been initialized, the initialization of its parent class needs to be triggered first
- Virtual chance ensures that the () methods of a class are properly locked and synchronized in a multithreaded environment
- The process of executing a class constructor () method. The class constructor () method is generated by the combination of the assignment actions of all class variables in the class automatically collected by the compiler and the statements in the static code block. (the class constructor is used to construct class information, not the constructor to construct the class object)
Example:
package reflection; /** * How are classes loaded? */ public class Test05 { public static void main(String[] args) { A a = new A(); System.out.println(A.m); /** * 1,Loading into memory will generate a Class object corresponding to a Class (each Class has only one Class object) * 2,Link. After the link is completed, m = 0 ---- "assigns a default value to m * 3,initialization * Initialize code block merge * <clinit>(){ * System.out.println("A Class static code block initialization ""); * m = 300; * m =100 * } * m = 100 */ } } class A{ static { System.out.println("A Class static code block initialization"); m = 300; } /** * Initialization execution: * m==300 * m==100 */ static int m =100; public A(){ System.out.println("A Class parameterless constructor initialization"); } }
result:
Class A static code block initialization
Class A parameterless constructor initialization
100
[note]: Class is generated when loading!
When does class initialization occur?
-
Active reference of class (class initialization must occur)
- When the virtual machine starts, first initialize the class where the main() method is located
- new is an object of a class
- Call static members (except final constants) and static methods of the class
- Using Java The method of lang.reflect package makes reflection calls to the class
- When initializing a class, if the parent class is not initialized, its parent class will be initialized first
-
Passive reference of class (class initialization will not occur)
- When accessing a static domain, only the class that actually declares the domain will be initialized. e.g. when a static variable of the parent class is referenced through a subclass, subclass initialization will not be caused
- Defining a class reference through an array does not trigger the initialization of this class
- The reference constant will not trigger the initialization of this class (the constant is stored in the constant pool of the calling class in the link phase) to generate the method of class reference
Example 1:
package reflection; /** * When does the test class initialize * */ public class Test06 { static { System.out.println("main Class is loaded"); } public static void main(String[] args) throws ClassNotFoundException { //1. The active reference is first the main method, then the parent class is loaded, and then the child class is loaded Son son = new Son(); //Reflection also produces active references // System.out.println("---------- split line ----------------"); // Class.forName("reflection.Son"); } } class Father{ static int b = 2; static { System.out.println("The parent class is loaded"); } } class Son extends Father{ static { System.out.println("Subclass loaded"); m =300; } static int m =100; static final int M = 1; }
result:
The main class is loaded
The parent class is loaded
Subclass loaded
Example 2:
package reflection; /** * When does the test class initialize * */ public class Test06 { static { System.out.println("main Class is loaded"); } public static void main(String[] args) throws ClassNotFoundException { //1. The active reference is first the main method, then the parent class is loaded, and then the child class is loaded // Son son = new Son(); //Reflection also produces active references System.out.println("----------Split line------------"); Class.forName("reflection.Son"); } } class Father{ static int b = 2; static { System.out.println("The parent class is loaded"); } } class Son extends Father{ static { System.out.println("Subclass loaded"); m =300; } static int m =100; static final int M = 1; }
result:
The main class is loaded
----------Split line------------
The parent class is loaded
Subclass loaded
Example 3:
package reflection; /** * When does the test class initialize * */ public class Test06 { static { System.out.println("main Class is loaded"); } public static void main(String[] args) throws ClassNotFoundException { //1. The active reference is first the main method, then the parent class is loaded, and then the child class is loaded Son son = new Son(); //Reflection also produces active references System.out.println("----------Split line------------"); Class.forName("reflection.Son"); } } class Father{ static int b = 2; static { System.out.println("The parent class is loaded"); } } class Son extends Father{ static { System.out.println("Subclass loaded"); m =300; } static int m =100; static final int M = 1; }
result:
The main class is loaded
The parent class is loaded
Subclass loaded
----------Split line------------
A method that does not generate a reference to a class
Example 1:
package reflection; /** * When does the test class initialize * */ public class Test06 { static { System.out.println("main Class is loaded"); } public static void main(String[] args) throws ClassNotFoundException { //1. The active reference is first the main method, then the parent class is loaded, and then the child class is loaded // Son son = new Son(); //Reflection also produces active references // System.out.println("---------- split line ----------------"); // Class.forName("reflection.Son"); //A method that does not generate a reference to a class System.out.println(Son.b);//Call the static variable of the parent class through Son } } class Father{ static int b = 2; static { System.out.println("The parent class is loaded"); } } class Son extends Father{ static { System.out.println("Subclass loaded"); m =300; } static int m =100; static final int M = 1; }
result:
The main class is loaded
The parent class is loaded
2
Example 2:
package reflection; /** * When does the test class initialize * */ public class Test06 { static { System.out.println("main Class is loaded"); } public static void main(String[] args) throws ClassNotFoundException { //1. The active reference is first the main method, then the parent class is loaded, and then the child class is loaded // Son son = new Son(); //Reflection also produces active references // System.out.println("---------- split line ----------------"); // Class.forName("reflection.Son"); //A method that does not generate a reference to a class // System.out.println(Son.b);// Call the static variable of the parent class through son Son[] array = new Son[5];//The array does not load the class array, but the space gives a name to this space } } class Father{ static int b = 2; static { System.out.println("The parent class is loaded"); } } class Son extends Father{ static { System.out.println("Subclass loaded"); m =300; } static int m =100; static final int M = 1; }
result:
The main class is loaded
Example 3:
package reflection; /** * When does the test class initialize * */ public class Test06 { static { System.out.println("main Class is loaded"); } public static void main(String[] args) throws ClassNotFoundException { //1. The active reference is first the main method, then the parent class is loaded, and then the child class is loaded // Son son = new Son(); //Reflection also produces active references // System.out.println("---------- split line ----------------"); // Class.forName("reflection.Son"); //A method that does not generate a reference to a class // System.out.println(Son.b);// Call the static variable of the parent class through son // Son[] array = new Son[5];// The array does not load the class array, but the space gives a name to this space System.out.println(Son.M);//Constants do not affect the initialization of parent and child classes } } class Father{ static int b = 2; static { System.out.println("The parent class is loaded"); } } class Son extends Father{ static { System.out.println("Subclass loaded"); m =300; } static int m =100; static final int M = 1; }
result:
The main class is loaded
1
Role of class loader
- The function of class loading: load the bytecode content of the class file into memory, convert these static data into the runtime data structure of the method area, and then generate a Java. Net file representing this class in the heap Lang. class object, as the access entry of class data in the method area.
- Class caching: the standard JavaSE class loader can find classes as required, but once a class is loaded into the class loader, it will remain loaded (cached) for a period of time. However, the JVM garbage collection mechanism (gc()) can recycle these class objects.
Source program (xxx.java file) -- "java compiler" -- "bytecode (xxx.class file) --" class loader "--" bytecode Checker "--" interpreter "--" operating system platform "
- Class loader is used to load classes into memory. The JVM specification defines loaders for classes of the following types.
- Boot class loader: written in C + +, it is the class loader of the JVM. It is responsible for the Java platform core library (rt.jar - Core Library) and is used to load the core class library. The loader cannot get directly.
- Extension class loader: it is responsible for the jar package or - D Java under jre/lib/ext directory Ext.dirs specifies the jar wrapper working library in the directory
- System class loader: responsible for java -classpath or - D Java class. The classes and jar s in the directory referred to in path are packaged into the work, which is the most commonly used loader.
Example:
package reflection; /** * Class loader */ public class Test07 { public static void main(String[] args) throws ClassNotFoundException { //Gets the loader of the system class ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); //Get the parent class loader of the system loader ---- extension class loader ClassLoader parent = systemClassLoader.getParent(); System.out.println(parent); //Get the parent class of the extension class loader -- "the root loader (written by the boot class loader c/c + +) can't be read by java ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //Test which loader loads the current class ClassLoader classLoader =Class.forName("reflection.Test07").getClassLoader(); System.out.println(classLoader); //Test who loaded the built-in classes in JDK ---- > root loader under RT package classLoader = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader); //How to get the path that the system class loader can load System.out.println(System.getProperty("java.class.path")); /** * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\charsets.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\deploy.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\access-bridge-64.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\cldrdata.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\dnsns.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\jaccess.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\jfxrt.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\localedata.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\nashorn.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\sunec.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\sunjce_provider.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\sunmscapi.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\sunpkcs11.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\zipfs.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\javaws.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\jce.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\jfr.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\jfxswt.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\jsse.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\management-agent.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\plugin.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\resources.jar; * D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\rt.jar; * C:\Users\Administrator\Desktop\java\project-1\out\production\Basic exercises; * D:\JavaIDE\IDEA\IntelliJ IDEA Community Edition 2020.2.3\lib\idea_rt.jar */ //Parental delegation mechanism // Customize a Java Lang.string -- > will be found in the system loader path extension loader path root loader path if found // There is Java Lang. string won't be customized by you. This is a security check } }
result:
sun.misc.Launcher
A
p
p
C
l
a
s
s
L
o
a
d
e
r
@
18
b
4
a
a
c
2
s
u
n
.
m
i
s
c
.
L
a
u
n
c
h
e
r
AppClassLoader@18b4aac2 sun.misc.Launcher
AppClassLoader@18b4aac2sun.misc.LauncherExtClassLoader@1b6d3586
null
sun.misc.Launcher$AppClassLoader@18b4aac2
null
D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\charsets.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\deploy.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\access-bridge-64.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\cldrdata.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\dnsns.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\jaccess.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\jfxrt.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\localedata.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\nashorn.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\sunec.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\sunjce_provider.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\sunmscapi.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\sunpkcs11.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\ext\zipfs.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\javaws.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\jce.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\jfr.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\jfxswt.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\jsse.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\management-agent.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\plugin.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\resources.jar;D:\JavaIDE\java8-home\jdk1.8.0_271\jre\lib\rt.jar;C:\Users\Administrator\Desktop\java\project-1\out\production \ basic exercises; D:\JavaIDE\IDEA\IntelliJ IDEA Community Edition 2020.2.3\lib\idea_rt.jar
Create an object for the runtime class
Gets the complete structure of the runtime class
Get the complete structure of the runtime class through reflection
Field,Method,Constructor,Superclass,Interface,Annotation
- All interfaces implemented
- Inherited parent class
- All constructors
- All methods
- All fields
- annotation
- ...
Example:
package reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * Get class information */ public class Test08 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class c1 = Class.forName("reflection.User"); //Get the name of the class System.out.println(c1.getName());//Get package name + class name System.out.println(c1.getSimpleName());//Get class name //Get the properties of the class System.out.println("==========================="); Field[] fields = c1.getFields();//Only public properties can be found for (Field field : fields) { System.out.println(field); } System.out.println("---------------------------"); fields = c1.getDeclaredFields();//All properties found for (Field field : fields) { System.out.println(field); } System.out.println("==========================="); //Gets the value of the specified property Field name = c1.getDeclaredField("name"); System.out.println(name); //Method to get class System.out.println("==========================="); Method[] methods = c1.getMethods();//Get all public methods of this class and its parent class for (Method method : methods) { System.out.println(method); } System.out.println("---------------------------"); methods =c1.getDeclaredMethods();//Get all methods of this class, including private methods for (Method method : methods) { System.out.println(method); } //Gets the specified method System.out.println("==========================="); Method getName = c1.getMethod("getName", null); System.out.println(getName); Method setName = c1.getMethod("setName", String.class);//Why is this parameter overloaded? Because the method name is the same, you need to use the parameter type to determine which method to put System.out.println(setName); System.out.println("==========================="); //Gets the specified constructor Constructor[] constructors = c1.getConstructors();//Get public method for (Constructor constructor : constructors) { System.out.println(constructor); } System.out.println("---------------------------"); constructors = c1.getDeclaredConstructors();//Get all methods of this class for (Constructor constructor : constructors) { System.out.println(constructor); } System.out.println("==========================="); //Gets the specified constructor Constructor constructor = c1.getConstructor(null); System.out.println(constructor); Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class); System.out.println(declaredConstructor); } }
result:
reflection.User
User
private java.lang.String reflection.User.name
private int reflection.User.id
private int reflection.User.age
private java.lang.String reflection.User.name
public java.lang.String reflection.User.toString()
public java.lang.String reflection.User.getName()
public int reflection.User.getId()
public void reflection.User.setName(java.lang.String)
public int reflection.User.getAge()
public void reflection.User.setId(int)
public void reflection.User.setAge(int)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
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 boolean java.lang.Object.equals(java.lang.Object)
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()
public java.lang.String reflection.User.toString()
public java.lang.String reflection.User.getName()
public int reflection.User.getId()
public void reflection.User.setName(java.lang.String)
private void reflection.User.test()
public int reflection.User.getAge()
public void reflection.User.setId(int)
public void reflection.User.setAge(int)
public java.lang.String reflection.User.getName()
public void reflection.User.setName(java.lang.String)
public reflection.User(java.lang.String,int,int)
public reflection.User()
public reflection.User(java.lang.String,int,int)
public reflection.User()
public reflection.User()
public reflection.User(java.lang.String,int,int)
Summary
- In the actual operation, the operation code to obtain the class information is not often developed
- Be familiar with Java Function of lang.reflect package, reflection mechanism
- How to get the names and modifiers of properties, methods, constructors, etc
What can I do with a Class object?
- Create Class object: call newInstance() method of Class object
- Class must have a parameterless constructor
- The constructor of the class needs sufficient access rights
reflection?
Can't you create an object without a parameterless constructor? As long as the constructor in the class is explicitly called during the operation and the parameters are passed in, the operation can be instantiated.
- The steps are as follows:
- Through getdeclaraedconstructor (Class
parameterTypes) gets the constructor of the specified parameter type of this class - Pass an object array into the formal parameters of the constructor, which contains all the parameters required by the constructor
- Instantiate objects through Constructor
Example:
package reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Dynamically create objects through reflection */ public class Test09 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //Get Class object Class c1 = Class.forName("reflection.User"); //Construct an object // User user =(User) c1.newInstance();// Essentially, a parameterless constructor is called // System.out.println(user); //Creating objects through constructors Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class); User user2 = (User) constructor.newInstance("Cool", 001, 18); System.out.println(user2); //Call normal methods through reflection User user3 =(User) c1.newInstance(); //Get a method by reflection Method setName = c1.getMethod("setName", String.class); //invoke means activate // (object, "value of method") setName.invoke(user3,"Blue "); System.out.println(user3); //Operation properties by reflection User user4 =(User) c1.newInstance(); Field name = c1.getDeclaredField("name");//name is a private property //Private properties cannot be operated directly. We need to turn off the security detection of the program and setAccessible(true) of properties or methods name.setAccessible(true); name.set(user4,"Xiao Honghong"); System.out.println(user4); } }
result:
User{name = 'cool', id=1, age=18}
User{name = 'Xiaolan', id=0, age=0}
User{name = 'xiaohonghong', id=0, age=0}
setAccessible
- Method, Field and Constructor objects all have setAccessible() methods
- setAccessible is a switch that enables and disables access security checks
- If the parameter value is true, it indicates that the java language access check should be cancelled when the reflected object is used
- Improve the efficiency of reflection. If reflection must be used in the code, and the code of this sentence needs to be called frequently, please set it to true
- So that private members that cannot be accessed can also be accessed
- If the parameter value is false, it indicates that the reflected object should implement java language access check
Performance comparison and analysis
Example:
package reflection; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Analyze performance issues */ public class Test10 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Test10.test01(); Test10.test02(); Test10.test03(); } //Normal mode call public static void test01(){ User user = new User(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { user.getName(); } long endTime = System.currentTimeMillis(); System.out.println("1 billion times in ordinary way:"+(endTime-startTime)+"ms"); } //Reflection mode call public static void test02() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class c1 =Class.forName("reflection.User"); User user = (User)c1.newInstance(); Method getName = c1.getDeclaredMethod("getName",null); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { getName.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("Reflection mode calls are executed 1 billion times:"+(endTime-startTime)+"ms"); } //Reflection mode call, close check public static void test03() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class c1 =Class.forName("reflection.User"); User user = (User)c1.newInstance(); Method getName = c1.getDeclaredMethod("getName",null); getName.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { getName.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("Close detection calls and execute 1 billion times:"+(endTime-startTime)+"ms"); } }
result:
1 billion times in ordinary way: 0ms
Reflection mode call execution 1 billion times: 3036ms
Close detection call execution 1 billion times: 1490ms
Reflection operation generics
- Java uses the generic erasure mechanism to introduce generics. Generics in Java are only used by the compiler javac to ensure data security and avoid forced type conversion. However, once the compilation is completed, all types related to generics are erased
- In order to manipulate these types through reflection, Java adds ParameterizedType, GenericArrayType, TypeVariable and WildcaredType to represent types that cannot be classified into Class but have the same name as the original type
- ParameterizedType: indicates a parameterized type, such as Collection
- GenericArrayType: indicates that an element type is a parameterized type or an array type of type variable
- TypeVariable: it is the public parent interface of various types of variables
- WildcaredType: represents a wildcard type expression
Example:
package reflection; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; /** * Get generics through reflection */ public class Test11 { public void test01(Map<String,User> map, List<User> userList){ System.out.println("test01"); } public Map<String,User> test02(){ System.out.println("test02"); return null; } public static void main(String[] args) throws NoSuchMethodException { Method method = Test11.class.getMethod("test01", Map.class, List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println(genericParameterType); if (genericParameterType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } System.out.println("--------------------------------------------"); Method method1 = Test11.class.getMethod("test02",null); Type genericReturnType = method1.getGenericReturnType(); if (genericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } }
result:
java.util.Map<java.lang.String, reflection.User>
class java.lang.String
class reflection.User
java.util.List<reflection.User>
class reflection.User
class java.lang.String
class reflection.User
Reflection operation annotation
- getAnnotations
- getAnnotation
Exercise: ORM
- Understand what is ORM? - Object relationship Mapping ----> Object relational mapping - Correspondence between class and table structure - Attribute and field correspondence - Object and record correspondence
- Requirement: use annotation and reflection to complete the mapping relationship between class and table structure
code:
package reflection; import java.lang.annotation.*; import java.lang.reflect.Field; /** * Practice reflection operation annotation */ public class Test12 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("reflection.Student2"); //Get annotations through reflection Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } System.out.println("------------------------"); //Get the value of annotation value TableHappy tableHappy = (TableHappy)c1.getAnnotation(TableHappy.class); System.out.println(tableHappy.value()); //Gets the annotation specified by the class Field name = c1.getDeclaredField("id"); FieldHappy annotation =name.getAnnotation(FieldHappy.class); System.out.println(annotation.columnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); } } @TableHappy("DB-student") class Student2{ @FieldHappy(columnName = "id",type = "int",length = 10) private int id; @FieldHappy(columnName = "age",type = "int",length = 10) private int age; @FieldHappy(columnName = "name",type = "varchar",length = 10) private String name; public Student2(){ } public Student2(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student2{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; } } //Annotation of class name @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface TableHappy{ String value(); } //Attribute annotation @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface FieldHappy{ String columnName(); String type(); int length(); }
result:
@reflection.TableHappy(value=DB-student)
DB-student
id
int
10