[Java Learning Summary] Annotations and Reflections

1. Annotation

1 Overview

  • Annotation is a new technology introduced by JDK5.0.
  • Most frameworks currently use annotations to simplify code.
  • Annotations are different from comments in that they can not only be seen by humans, but also read by programs.
  • Notes are equivalent to adding additional auxiliary information to the program.
  • Annotations can be used on package, class, method, field, etc.

2. Built-in annotations

It is an annotation that acts on the code and is defined in java.lang.

  1. @Override: Indicates that the method is to override the method of the parent class.

  2. @Deprecated: Indicates that the method is outdated and is not recommended, but it is not impossible to use.

  3. @SuppressWarnings: Suppress warnings, can be used to turn off compiler warnings, and can pass parameters.

3. Meta annotations

Annotations that act on other annotations are defined in java.lang.annotation.

  1. @Target : Indicates where our annotations can be used.
    (1).TYPE: This annotation can be used for class, interface (including annotation type) or enum declaration.
    (2).FIELD: This annotation can be used for field declarations (including enum instances).
    (3).METHOD: This annotation can be used for method declarations.
    (4).PARAMETER: This annotation can be used for parameter declaration.
    (5).CONSTRUCTOR: This annotation can be used for constructor declarations.
    (6).LOCAL_VARIABLE: This annotation can be used for local variable declaration.
    (7).ANNOTATION_TYPE: This annotation can be used for annotation declaration.
    (8).PACKAGE: This annotation can be used for package declaration.
    (9).TYPE_PARAMETER: This annotation can be used for parameter type declaration. Newly added in 1.8.
    (10).TYPE_USE: This annotation can be used for type declaration. Newly added in 1.8.
  2. @Retention: Indicates where the annotation takes effect and is used to describe the life cycle of the annotation. Source code level (SOURCE) < class file level (CLASS) < runtime level (RUNTIME).
  • SOURCE: The annotation will be discarded by the compiler.
  • CLASS: Annotations are available in class files, but will be discarded by the JVM.
  • RUNTIME: Annotation information will also be retained at runtime (JVM), so the annotation information can be read through the reflection mechanism.
  1. @Document: Indicates whether to generate our annotations in Javadoc.

  2. @Inherited: Subclasses can inherit annotations from parent classes.

4. Custom annotations

2. Reflection

1. What is reflection

Reflection is the key technology of Java, which is called "quasi-dynamic language". The reflection mechanism allows the program to obtain the internal information of any class by means of the Reflection API during execution, and can directly manipulate the internal properties and methods of any object.
The normal way is to instantiate an object via new with the full "package class" name. The reflection method can obtain the complete "package class" name by instantiating the object and calling the getClass() method.

2. Class class

The getClass() method is defined in the Object class, and the return value of this method is the Class class, which is the source of Java reflection. For any class you want to dynamically load and run, you must first obtain the corresponding Class object.

    //获取Class对象的方法
    public static void main(String[] args) throws ClassNotFoundException {
    
    

        //方式一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1);

        //方式二:forName获得
        Class c2 = Class.forName("包名+类名");
        System.out.println(c2);

        //方式三:通过类名.class获得
        Class c3 = Person.class;
        System.out.println(c3);
    }

3. Class loader

  1. Class loading process:
    (1) Load (Load): Load the class file into memory and create a java.lang.Class object for it. This process is done by the class loader.
    (2) Link (Link): The process of merging the binary data of the class into the JVM.
    (3) Initialize (Initialize): The process of executing the class constructor () method. The JVM is responsible for initializing the class.

  2. The role of class loading: load the bytecode content of the class file into the memory, and convert these static data into the runtime data structure of the method area, and then generate a java.lang.Class object representing this class in the heap as The access entry of class data in the method area.

	public static void main(String[] args) throws ClassNotFoundException {
    
    
        //获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类加载器-->扩展加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        //获取扩展类加载器的父加载器-->根加载器(C/C++)
        ClassLoader parentParent = parent.getParent();
        System.out.println(parentParent);
	}

4. Obtain information from the Class object

(1) Access the attributes contained in the class corresponding to Class

  1. Batch attributes:
    public Field[] getFields(): Get all public attributes
    public Field[] getDeclaredFields(): Get all attributes
  2. Get a single property:
    public Field getField(String name): get a single public property
    public Field getDeclaredField(String name): get any property

(2) Access the methods contained in the class corresponding to Class

  1. Batch methods:
    public Method[] getMethods(): Get all public constructors
    public Method[] getDeclaredMethods(): Get all constructors
  2. Get a single method:
    public Method getMethod(String name, Class... parameterTypes): get a single public method
    public Method getDeclaredMethod(String name, Class... parameterTypes): get any method

(3) Access the constructor contained in the class corresponding to Class

  1. Batch method:
    public Constructor[] getConstructors(): Get all public constructors
    public Constructor[] getDeclaredConstructors(): Get all constructors
  2. Get a single method:
    public Constructor getConstructor(Class...parameterTypes): get a single public constructor
    public Constructor getDeclaredConstructor(Class...parameterTypes): get any constructor

The test code is as follows:

  1. First create a User entity class
class User{
    
    
    private int id;
    private int age;
    private String name;

    public User() {
    
    }

    public User(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;
    }
}
  1. Obtain the methods, properties and constructors of the entity class through the Class object
   public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
    
    
        Class c1 = Class.forName("com.carry.reflection.User");

        //获得类的名字
        System.out.println(c1.getName());//包名+类名
        System.out.println(c1.getSuperclass());//类名

        //获得类的属性
        System.out.println("=======================");
        Field[] fields = c1.getFields();//只能找到public的属性
        fields = c1.getDeclaredFields();//找到全部属性
        for(Field field : fields){
    
    
            System.out.println(field);
        }

        //获得指定属性的值
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        //获得类的方法
        Method[] methods = c1.getMethods();//获得本类及其父类的所有方法
        for (Method method : methods) {
    
    
            System.out.println("正常的"+method);
        }
        methods = c1.getDeclaredMethods();//获得本类的所有方法
        for (Method method : methods) {
    
    
            System.out.println("getDeclaredMethods"+method);
        }

        //获得指定方法
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        //获得类的构造器
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
    
    
            System.out.println(constructor);
        }
        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
    
    
            System.out.println("Declared"+constructor);
        }

        //获得指定的构造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(int.class,int.class,String.class);
        System.out.println("指定"+declaredConstructor);
    }

5. Class dynamically creates objects

  1. Create an object using the newInstance() method of the Class object
  2. Create objects using Constructor objects

The test code is as follows:

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
    
    
        //获得Class对象
        Class c1 = Class.forName("com.carry.reflection.User");

        //构造一个对象
        User user = (User) c1.newInstance();//本质是调用了类的无参构造器
        System.out.println(user);

        //通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(int.class, int.class, String.class);
        User user2 = (User)constructor.newInstance(1, 18, "hello");
        System.out.println(user2);

        //通过反射调用普通方法
        User user3 = (User) c1.newInstance();
        //通过反射获取一个方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //invoke:激活的意思(对象,“方法的值”)
        setName.invoke(user3,"hi");
        System.out.println(user3.getName());

        //通过反射操作属性
        System.out.println("======================");
        User user4 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");

        //不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true)
        name.setAccessible(true);//取消安全检测
        name.set(user4,"hi2");
        System.out.println(user4.getName());
    }

6. Get generics through reflection

The generic type in the method can be obtained through the reflection method.

  1. First create two test methods, the return value and parameters of these two methods are generic.
    public void test01(Map<String,User> map, List<User> list){
    
    
        System.out.println("test01");
    }

    public Map<String,User> test02(){
    
    
        System.out.println("test02");
        return null;
    }
  1. The generics of the two methods are obtained through Class respectively. .
    public static void main(String[] args) throws NoSuchMethodException {
    
    
        Method method = Test.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);
                }
            }
        }

        method = Test.class.getMethod("test02",null);
        Type genericReturnType = method.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType){
    
    
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
    
    
                System.out.println(actualTypeArgument);
            }
        }
    }

7. Obtain annotations through reflection

  1. Define two annotations
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableHello{
    
    
    String value();
}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldHello{
    
    
    String columnName();
    String type();
    int length();
}
  1. Define an entity class and use these two annotations in the entity class
@TableHello("db_student")
class Student{
    
    

    @FieldHello(columnName = "db_id",type = "int",length = 10)
    private int id;
    @FieldHello(columnName = "db_age",type = "int",length = 10)
    private int age;
    @FieldHello(columnName = "db_name",type = "varchar",length = 5)
    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;
    }
}
  1. Get the annotations in the entity class in the main method
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
    
    
        Class c1 = Class.forName("com.carry.reflection.Student");

        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
    
    
            System.out.println(annotation);
        }

        //获得注解的value的值
        TableHello tableHello = (TableHello) c1.getAnnotation(TableHello.class);
        String value = tableHello.value();
        System.out.println(value);

        //获得类指定的注解
        Field field = c1.getDeclaredField("name");
        FieldHello annotation = field.getAnnotation(FieldHello.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }

Guess you like

Origin blog.csdn.net/qq_43647936/article/details/121088534