java foundation 3 (annotation and reflection mechanism)

Posted by gofer on Fri, 21 Jan 2022 13:27:16 +0100

1, Annotation

1. What is annotation?

1. Concept
Annotations in java are mainly used to mark code or combine other methods, such as reflection, to realize the transmission of values. In addition, annotations are also used more in the framework.
There are seven kinds of annotations in java, including @ override, @ deprecated, @ suppresswarnings and four meta annotations (annotations representing annotations). After jdk7, it gradually increased to 10 species.

By source:
1.java comes with comments:
@Override
Indicates that you intend to override the method declaration in the superclass.
@Deprecated
This annotation can be used as a rhetorical device, attribute or class to indicate that programmers are not encouraged to use such elements, usually because they are dangerous or have a better choice.
@SuperWarnings
This annotation is mainly used to suppress warning messages. Different from the first two annotations, we must give annotation parameters to use it.
Meta annotation:
@Retention - identifies how the annotation is saved, whether it is only in the code, incorporated into the class file, or can be accessed through reflection at run time (that is, which of the three life cycles defined above).
@Retention
**This annotation is used to describe the lifecycle of the annotation.
Value RetentionPolicy:
SOURCE is valid in the SOURCE file (i.e. SOURCE file retention)
class is valid in the class file (i.e. class is reserved)
RUNTIME is valid at RUNTIME (i.e. RUNTIME retention)

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
	//The parameter is empty by default
   String value() default "";
}

Note: when it is RUNTIME, it can be read by the reflection mechanism
This annotation is used to describe the lifecycle of the annotation.
Value RetentionPolicy:
SOURCE is valid in the SOURCE file (i.e. SOURCE file retention)
class is valid in the class file (i.e. class is reserved)
RUNTIME is valid at RUNTIME (i.e. RUNTIME retention)
In general, we use RUNTIME. In this way, we can also read the annotation through the reflection mechanism when the program is running.

@Documented - marks whether these annotations are included in the user document.
@Target - marks which Java member this annotation should be.
usage method:
This annotation is mainly used to describe the scope of use of the annotation. In other words, it is where the annotation defined by ourselves can be used. Value of modified range ElementType:
PACKAGE: PACKAGE
Class, interface, enumeration, Annotation TYPE: TYPE
Type member (method, constructor, member variable, enumeration value)
CONSTRUCTOR: used to describe the CONSTRUCTOR.
FIELD: used to describe the FIELD.
METHOD: used to describe the METHOD
Method parameters and local variables
LOCAL_VARIABLE: used to describe local variables.
PARAMETER: used to describe parameters

We use ElementType Method as an example.

@Target(ElementType.METHOD)
public @interface TestAnnotation {
	//The parameter is empty by default
    String value() default "";
}

@Inherited - marks which annotation class this annotation inherits from (the default annotation does not inherit from any class)
New note:
@SafeVarargs - Java 7 starts to support, ignoring any warnings generated by method or constructor calls that use parameters as generic variables.
@Functional interface - Java 8 began to support, identifying an anonymous function or functional interface.
@Repeatable - Java 8 began to support, identifying that an annotation can be used multiple times on the same declaration.

2. Third party annotations, such as those in Spring;

3. User defined annotation, defined with @ interface keyword.
Format: public @interface annotation name {definition body}
1. When using @ interface custom annotation, it automatically inherits Java lang.annotation. Annotation interface
2. Each of these methods actually declares a configuration parameter
3. The name of the method is the name of the parameter
4. The return value type is the type of parameter (the return value type can only be basic type, Class, String and enum)
5. You can declare the default value of the parameter through default
5. If there is only one parameter member, the general parameter name is value
We must have a value when using annotation elements. We can define the default value, empty string, 0 or - 1

public @interface TestAnnotation {
    //The parameter is empty by default
    String value() default "";
}

2, What is reflection:

(1) The core of Java reflection mechanism is to dynamically load classes and obtain class details when the program is running, so as to operate the properties and methods of classes or objects. The essence is that after the JVM obtains the class object, it decompiles it through the class object to obtain various information of the object.
(2) Java is a language that compiles first and then runs. The type of object in the program is determined at the compilation time. When the program runs, it may need to dynamically load some classes. These classes are not loaded into the JVM because they were not used before. Through reflection, you can dynamically create objects and call their properties at run time without knowing who the running object is at compile time in advance.
2. Principle of reflection: (learn from others' drawings)

3. Advantages and disadvantages of reflection:
1. Advantages: obtain various contents of classes at run time and decompile them. For Java, a language that compiles first and then runs, it is easier to realize object-oriented.
2. Disadvantages:
(1) Reflection consumes some system resources, so if you don't need to create an object dynamically, you don't need to use reflection.
(2) Reflection can ignore permission checking when calling methods, which may destroy encapsulation and lead to security problems.
4. Purpose of reflection:
1. Decompile: class–>. java
2. Access the properties, methods and construction methods of java objects through reflection mechanism
3. When we are using an IDE, such as Ecplise, when we input an object or class and want to call its properties and methods, the compiler will automatically list its properties or methods as soon as we press the dot. Reflection is used here.
4. The most important use of reflection is to develop various common frameworks. For example, many frameworks (Spring) are configured (such as configuring beans through XML files). In order to ensure the universality of the framework, they may need to load different classes or objects and call different methods according to the configuration file. At this time, reflection must be used to dynamically load the loaded objects at runtime.
For example, in the development process using the struts framework, we usually use struts Configure Action in XML
As well as loading the database driver, reflection is also used.
Class.forName(“com.mysql.jdbc.Driver”); // Dynamic loading MySQL driver

//struts. Configure Action in XML
<action name="login" class="org.ScZyhSoft.test.action.SimpleLoginAction" method="execute">   
    <result>/shop/shop-index.jsp</result>           
    <result name="error">login.jsp</result>       
</action>

5. Basic use of reflection:
1. There are three main ways to obtain Class:
(1)Object–>getClass
(2) Any data type (including basic data types) has a "static" class attribute
(3) Through the static method of class: forName(String className) (most commonly used)

/*
* Three main methods to obtain Class
* Among the three methods, the third one is often used. What do you need to reflect when you have the first object,
* The second is to import class packages. The dependency is too strong. If you don't import packages, you will throw compilation errors.
* The third method is generally used. A string can be passed in or written in the configuration file.
* */
public  class day6 {
    public static void main(String[] args) throws ClassNotFoundException {
        //The first way is to get the Class object
        Stu stu = new Stu("yan", 20);
        Class stuClass = stu.getClass();//Get Class object
        System.out.println(stuClass.getName());
        //The second method is to get the class object
        Class staClass2 = Stu.class;
        System.out.println(stuClass == staClass2);//Judge the information obtained in the first or second method
        //Third acquisition
        Class stuClass3 = Class.forName("fanshe.Student");
        System.out.println(staClass2 == stuClass3);
    }
}

Note that during operation, only one Class object is generated for a Class, so the print result is true;

/**
 * Create instance: generate objects by reflection
 * */
public  class day6 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //Use the newInstance() method of the Class object
        Class<?> c = String.class;
        Object str = c.newInstance();
        //Obtain the specified Constructor object through the Class object, and then call the newInstance() method of the Constructor object to create the object
        Class<?> str2 = String.class;
//Gets the specified Constructor constructor object through the Class object
        Constructor constructor=str2.getConstructor(String.class);
//Create an instance from the constructor:
        Object obj = constructor.newInstance("hello");
        System.out.println(str);
    }
}

2. An example of determining whether it is a class:
We can judge by isInstance() method of Class object in reflection. It is a native method.
public native boolean isInstance(Object obj);
3. Create instance: there are two main methods to generate objects through reflection:
(1) Use the newInstance() method of the Class object to create an instance of the Class corresponding to the Class object.

(2) First obtain the specified Constructor object through the Class object, and then call the newInstance() method of the Constructor object to create the object. This method can construct the instance of the Class with the specified Constructor.

Other uses of reflection methods – run profile content through reflection:
Student class:
public class Student {
public void show(){
System.out.println("is show()");
}
}

/**
 * Create instance: generate objects by reflection
 * */
public  class day6 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //Use the newInstance() method of the Class object
        Class<?> c = String.class;
        Object str = c.newInstance();
        //Obtain the specified Constructor object through the Class object, and then call the newInstance() method of the Constructor object to create the object
        Class<?> str2 = String.class;
//Gets the specified Constructor constructor object through the Class object
        Constructor constructor=str2.getConstructor(String.class);
//Create an instance from the constructor:
        Object obj = constructor.newInstance("hello");
        System.out.println(str);
    }

/**
 * The Class object can be used to obtain: constructor, member variable and member method in a Class; And visit members;
 *
 * 1.Get construction method:
 * 		1).Batch method:
 * 			public Constructor[] getConstructors(): All "public" construction methods
            public Constructor[] getDeclaredConstructors(): Get all construction methods (including private, protected, default and public)
 * 		2).Get a single method and call:
 * 			public Constructor getConstructor(Class... parameterTypes):Get a single "public" constructor:
 * 			public Constructor getDeclaredConstructor(Class... parameterTypes):Get "a constructor" can be private, protected, default, or public;
 * 		3).Call constructor:
 * 			Constructor-->newInstance(Object... initargs)
 */
public class day6{
    public static void main(String[] args)throws Exception {
        //1 get Class object
        Class stuClass= Class.forName("yanqing.Student");
        //All common construction methods
        Constructor[] conArray=stuClass.getConstructors();
        for(Constructor c:conArray){
            System.out.println(c);
        }
        //All construction methods (including private, protected, default, public)
        conArray=stuClass.getDeclaredConstructors();
        for(Constructor c:conArray){
            System.out.println(c);
        }
        //Get public, parameterless construction method
        Constructor con=stuClass.getConstructor(null);
        //1> . because it is a parameterless construction method, the type is null and can be written without writing: what is needed here is the type of a parameter. Remember that it is a type
        //2> , returns the class object describing the parameterless constructor.
        System.out.println(con);
        //Call constructor
        Object obj=con.newInstance();
        //Call the private constructor and call
        con=stuClass.getDeclaredConstructor(char.class);
        obj=con.newInstance("male");
    }
}
/**
 * Get the member variable and call
 * */
public class day6{
    public static void main(String[] args)throws Exception {
       Class stuClass=Class.forName("yanqing.Student");
       //Get all public fields
        Field[] fields=stuClass.getFields();
        for(Field f:fields){
            System.out.println(f);
        }
        //Get all fields
        fields=stuClass.getDeclaredFields();
        for (Field f:fields){
            System.out.println(f);
        }
        //Get all public fields * * * and call
        Field f=stuClass.getField("name");
        System.out.println(f);
        Object obj=stuClass.getConstructor().newInstance();
        f.set(obj,"yanqing");
        Student stu=(Student)obj;
        System.out.println("Verification Name:"+stu.name);
        //Get private field * * * * and call
        f=stuClass.getDeclaredField("phoneNum");
        System.out.println(f);
        f.setAccessible(true);
        f.set(obj,"561561616");
        System.out.println("Verification phone:"+stu);
    }
}

/**
 * Get the member method and call:
 *
 * 1.Batch:
 * 		public Method[] getMethods():Get all "public methods"; (methods that contain the parent class also contain the Object class)
 * 		public Method[] getDeclaredMethods():Get all member methods, including private (excluding inherited)
 * 2.Get a single:
 * 		public Method getMethod(String name,Class<?>... parameterTypes):
 * 					Parameters:
 * 						name : Method name;
 * 						Class ... : Class type object of formal parameter
 * 		public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
 *
 * 	 Call method:
 * 		Method --> public Object invoke(Object obj,Object... args):
 * 					Parameter Description:
 * 					obj : The object to call the method;
 * 					args:The argument passed when calling the method;
):
 */
public class day6{
    public static void main(String[] args)throws Exception {
        Class stuClass=Class.forName("yanqing.Student");
        //Get all public methods
        Method[] methods=stuClass.getMethods();
        for(Method m:methods){
            System.out.println(m);
        }
        methods=stuClass.getDeclaredMethods();
        for(Method m:methods){
            System.out.println(m);
        }
        //Get the common show1() method
        Method m=stuClass.getMethod("show1", String.class);
        System.out.println(m);
        Object obj=stuClass.getConstructor().newInstance();
        m.invoke(obj,"Liu Yifei");

        m=stuClass.getDeclaredMethod("show4", int.class);
        System.out.println(m);
        m.setAccessible(true);
        Object result=m.invoke(obj,20);
        System.out.println("Return value:"+result);
    }
}

Other uses of reflection methods – cross generic checking by reflection:
Generics are used at compile time. After compilation, generics are erased (disappear), so generics can be checked by reflection
Test class:

/*
 * Cross generic checking by reflection
 * For example, if there is a collection of String generics, how can we add a value of Integer type to this collection?
 */
public class Demo {
	public static void main(String[] args) throws Exception{
		ArrayList<String> strList = new ArrayList<>();
		strList.add("aaa");
		strList.add("bbb");
	//	strList.add(100);
		//Get the Class object of ArrayList, call the add() method in reverse to add data
		Class listClass = strList.getClass(); //Get the bytecode object of the strList object
		//Get the add() method
		Method m = listClass.getMethod("add", Object.class);
		//Call the add() method
		m.invoke(strList, 100);
		//Traversal set
		for(Object obj : strList){
			System.out.println(obj);
		}
	}
}
Console output:
aaa
bbb
100

Topics: Java Back-end