Annotation and reflection
Comment: give people an explanation of the program so that people can better understand the program
Annotation: it can not only give people an explanation of the program, but also be recognized by the compiler and check the constraint code
Format of Annotation:
@Comment name (some special parameter values can be added)
Built in annotation
1,@override
This annotation is only used for rhetoric, indicating that one method declaration intends to override another method declaration in the superclass.
2,@Deprecated
Indicates that programmers are not encouraged to use such elements. Usually, it is dangerous or has a better choice, but it can still be used
3,@SuppressWarnings
Used to suppress compile time warnings
Meta annotation
Responsible for annotation of other annotations
@Target is used to describe the scope of use of annotations (class, method, constructor or what)
@Retention indicates the level at which the annotation information is saved. It is used to describe the annotation life cycle (source < class < runtime)
@Document indicates that the annotation will be included in the javadoc
@Inherited indicates that the child class can inherit the annotation from the parent class
Custom annotation
@Interface is used to customize annotation format: public @interface annotation name (define 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 parameter type (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
Annotation elements must have values. When defining annotation elements, we often use the empty string 0 as the default value
@MyAnnotation(schools="southeast") public class Test1 { @MyAnnotation1("kk") @MyAnnotation(name="main",schools="southeast") public static void main(String[] args) { System.out.println("hello"); } } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation{ //Annotation parameter type parameter name (); //String name(); String name() default "";//If there is a default value, you can not write the parameter int age() default 0; int id() default -1;//The default value is - 1, which means it does not exist. indexof returns - 1 if it cannot be found String[] schools(); } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation1{ String value();//Only when the parameter name is defined as value, the above code can not write the parameter =, the default value }
Dynamic language and static language
Dynamic language: a language whose structure can be changed at runtime (for example, new functions, objects and even code can be introduced, existing functions can be deleted or other structural changes). Generally speaking, it means that the code can change its structure according to some conditions at runtime
Main dynamic languages: Object-C, c#, Javascript, PHP, Python
Static language: as opposed to dynamic language, a language whose runtime structure cannot be changed becomes a static language
Main static languages: Java, C, C++
The Java language can achieve quasi dynamic performance through reflection mechanism
Reflection
During execution, the reflection runtime obtains the internal information of any class with the help of the Reflection API, and directly operates the internal properties and methods of any object
Advantages and disadvantages of reflection:
1. Advantages: it can dynamically create objects and compile, reflecting great flexibility
2. Disadvantages: since reflection is an explanatory language, its efficiency is lower than that of direct execution
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 a class
Reflection method
[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-ysnejs4m-1633065637510) (C: \ users \ 84054 \ appdata \ roaming \ typora user images \ image-20210925182642210. PNG)]
Get the method 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.
System.out.println(User.class);
-
If an instance of a Class is known, call the getClass () method of the instance to obtain the Class object
User u1=new User("Mike",10,1); System.out.println(u1.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 c1=Class.forName("Annotation.User");
- The built-in basic data type can directly use the class name. Type
Class c4=Integer.TYPE; System.out.println(c4);
- You can also use ClassLoader
Where types can have class es
Class c1=Class.class; //Class can create class objects Class c2=Comparable.class; //interface can create class objects Class c3= ElementType.class; //Enum can create class objects Class c4=String[].class; //A unary array can create a class object Class c5=int[][].class; //Binary arrays can create class objects Class c6=int.class; //Basic data types can create class objects Class c7=Override.class; //Annotations can create class objects Class c8=void.class; //void can create a class object 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);
The output result of the corresponding class above
class java.lang.Class
interface java.lang.Comparable
class java.lang.annotation.ElementType
class [Ljava.lang.String;
class [[I
int
interface java.lang.Override
void
Note: you can copy and paste multiple data with alert
Java memory map
The method area of Java stores the information of each class (including class name, method information and field information), static variables, constants and code compiled by the compiler; the heap data area is used to store objects and arrays (special objects);
[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-ckvj01r3-1633065637515) (C: \ users \ 84054 \ appdata \ roaming \ typora \ user images \ image-20210928223041107. PNG)]
As can be seen from the above figure, stack frames are stored in the Java stack, and each stack frame corresponds to a called method. The stack frame includes local variables, operand stack, and references to the runtime constant pool of the class to which the current method belongs (the concept of runtime constant pool is discussed in the method area) (Reference to runtime constant pool), method return address, and some additional information.
JAVA class loader
The function of class loader: load the bytecode content of class file into memory, convert these static data into the runtime data structure of method area, and then generate a java.lang.class object representing this class in the heap as the access interface of class data in method area
Acquisition of JAVA class loader
//Get system class loader ClassLoader loader = ClassLoader.getSystemClassLoader(); System.out.println(loader); //Get the parent class loader of the system class loader -- > platform class loader ClassLoader parent = loader.getParent(); System.out.println(parent); //Gets the root loader compiled by C/C + + ClassLoader root = parent.getParent(); System.out.println(root); //Get this class loader (this class is called Classload) ClassLoader classLoader = ClassLoad.class.getClassLoader(); System.out.println(classLoader); //Get the parent class loader of this class ClassLoader parent1 = classLoader.getParent(); System.out.println(parent1);
The running results of the above code
jdk.internal.loader.ClassLoaders
A
p
p
C
l
a
s
s
L
o
a
d
e
r
@
2
f
0
e
140
b
j
d
k
.
i
n
t
e
r
n
a
l
.
l
o
a
d
e
r
.
C
l
a
s
s
L
o
a
d
e
r
s
AppClassLoader@2f0e140b jdk.internal.loader.ClassLoaders
AppClassLoader@2f0e140bjdk.internal.loader.ClassLoadersPlatformClassLoader@27d6c5e0
null
jdk.internal.loader.ClassLoaders
A
p
p
C
l
a
s
s
L
o
a
d
e
r
@
2
f
0
e
140
b
j
d
k
.
i
n
t
e
r
n
a
l
.
l
o
a
d
e
r
.
C
l
a
s
s
L
o
a
d
e
r
s
AppClassLoader@2f0e140b jdk.internal.loader.ClassLoaders
AppClassLoader@2f0e140bjdk.internal.loader.ClassLoadersPlatformClassLoader@27d6c5e0
Get reflection object
User u= new User(); //Gets the class of an object from an object Class aClass = u.getClass(); System.out.println(aClass); //Get the class according to the specific name of the class Class aClass1 = Class.forName("Annotation.User"); System.out.println(aClass1); //Get class from class Class userClass = User.class; System.out.println(userClass);
Acquisition of JAVA class methods and properties
Class test = Class.forName("Annotation.User");//Get a class first //Get method of public type Method[] methods = test.getMethods(); for (Method method : methods) { System.out.println(method); } //Get all types of methods Method[] methods1 = test.getDeclaredMethods(); for (Method method : methods1) { System.out.println(method); } //Gets a specified method Method getName = test.getDeclaredMethod("getName",null); System.out.println(getName); //Get properties of public permission Field[] fields = test.getFields(); for (Field field : fields) { System.out.println(field); } //Get all types of properties, including private type Field[] fields1 = test.getDeclaredFields(); for (Field field : fields1) { System.out.println(field); } //Gets a specified property Field id = test.getDeclaredField("id"); System.out.println(id);
Creating objects with reflection classes
Create Class object: call newinstance() method of Class object
Two conditions are required to create an object using the above method:
- Class must have a parameterless constructor
- The constructor of the class needs sufficient access rights
How to create an object for a class without a parameterless constructor?
Creating objects through constructors
- Get the constructor of the formal parameter type specified by this Class through getdeclaraedconstructor (Class... parameterTypes) of Class class
- Pass an object array into the formal parameters of the constructor, which contains all the parameters required by the constructor
- Strengthen objects through Constructor
//Get class object Class t = Class.forName("Annotation.User"); //Construct an object (create an object through a parameterless constructor) User user =(User) t.newInstance(); System.out.println(user); //Creating objects through constructors Constructor constructor = t.getDeclaredConstructor(String.class, int.class, int.class); User user1=(User) constructor.newInstance("Network security",18,1); System.out.println(user1); //Get a method through reflection Method setName = t.getDeclaredMethod("setName", String.class); setName.invoke(user1,"security"); System.out.println(user1); System.out.println(user1.getName()); //Modify attributes through reflection Field name = t.getDeclaredField("name"); //When private properties or methods cannot be operated directly, we can access them by setting their access permissions //Set reflection permission to accessible type name.setAccessible(true); name.set(user1,"kkkkk"); System.out.println(user1);
The results of the above code execution
User{name='null', age=0, id=0}
User{name = 'network security', age=18, id=1}
User{name = 'safe', age=18, id=1}
security
User{name='kkkkk', age=18, id=1}
Note: the User class mentioned above is a pre created class with certain properties and methods, and its code is as follows
class User{ private String name; private int age; private int id; public User() { } public User(String name, int age, int id) { this.name = name; this.age = age; this.id = id; } 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; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + '}'; } }
Performance analysis of objects created by various methods
static final long num=1000000000; public static void test01(){ User user=new User(); long starttime=System.currentTimeMillis(); for (int i = 0; i < num; i++) { user.getName(); } long endtime=System.currentTimeMillis(); System.out.println("Time spent creating normal object methods:"+(endtime-starttime)+"ms"); } public static void test02() throws IllegalAccessException, InstantiationException { User user=new User(); Class user1 = user.getClass(); User u =(User) user1.newInstance(); long starttime=System.currentTimeMillis(); for (int i = 0; i < num; i++) { u.getName(); } long endtime=System.currentTimeMillis(); System.out.println("Time spent creating objects for reflection classes:"+(endtime-starttime)+"ms"); } public static void test03() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { User user=new User(); Class user2 = user.getClass(); Method getName = user2.getDeclaredMethod("getName"); long starttime=System.currentTimeMillis(); for (int i = 0; i < num; i++) { getName.invoke(user, null); } long endtime=System.currentTimeMillis(); System.out.println("Time spent creating object with security check reflection method call:"+(endtime-starttime)+"ms"); } public static void test04() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { User user=new User(); Class user2 = user.getClass(); Method getName = user2.getDeclaredMethod("getName"); getName.setAccessible(true); long starttime=System.currentTimeMillis(); for (int i = 0; i < num; i++) { getName.invoke(user, null); } long endtime=System.currentTimeMillis(); System.out.println("Time spent creating object without security check reflection method call:"+(endtime-starttime)+"ms"); } public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { test01(); test02(); test03(); test04(); }
Time spent creating normal object method: 914ms
Time taken for reflection class to create object: 749ms
Time spent creating object with security check reflection method call: 3591ms
Time spent creating object without security check reflection method call: 1633ms
How to use reflection to obtain specific information of annotations
public class ReflectAnnotation { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { //Get a class Class s = Class.forName("Annotation.Student"); //Get the annotation of this class Annotation[] annotations = s.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //Get an object of class annotation name annotation = (name) s.getAnnotation(name.class); //Get the internal content of class annotation String value = annotation.value(); System.out.println(value); //An object that gets the id attribute of the class Field id = s.getDeclaredField("id"); //Get all annotation information under the object Annotation[] annotations1 = id.getAnnotations(); for (Annotation annotation1 : annotations1) { System.out.println(annotation1); } //Get the specific information of an annotation under the id attribute object RefineField annotation1 =(RefineField) id.getAnnotation(RefineField.class); System.out.println(annotation1.column()); System.out.println(annotation1.type()); System.out.println(annotation1.length()); } } @name("Student") class Student{ @RefineField(column = "id",type = "int",length = 10) private int id; @RefineField(column = "age",type = "int",length = 10) private int age; @RefineField(column = "name",type = "int",length = 10) private String name; public Student() { } public Student(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 "Student{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; } } //Define an annotation about the class @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface name{ String value(); } //Define an annotation about attributes @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface RefineField{ String column(); String type(); int length(); }
The running answer of the above code
@Annotation.name("Student")
Student
@Annotation.RefineField(column="id", type="int", length=10)
id
int
10
"id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; }
}
//Define an annotation about the class
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface name{
String value();
}
//Define an annotation about attributes
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface RefineField{
String column();
String type();
int length();
}
**The running answer of the above code** @Annotation.name("Student") Student @Annotation.RefineField(column="id", type="int", length=10) id int 10